X

LiveSensitive

Direct replies to a post

GET/data-api/v2/x/tweets/{id}/replies
Scope
scrape:live
Freshness
live read
Group
X
Platforms
1 of 7

What this endpoint answers

The posts whose parent is this one. X returns a whole conversation module - the root, the author's own continuation, unrelated context - and only some of it answers the question, so every row is checked against the parent id before it is counted. A limit of twenty means twenty replies, not twenty rows of which four are replies.

This is a live read: it goes to the platform at request time, returns cache_age_s = 0, and is metered against a separate live-per-minute bucket on top of your tier. It needs the scrape:live scope (Live scrape): Read from the platform itself rather than from the catalog: a profile or channel on any of the seven platforms, and on X the whole content layer - timelines, posts, replies, quotes, threads, followers, search, lists and communities.

Good to know

  • Direct replies only. For the whole conversation - the author's thread plus everything hanging off it - use /x/tweets/{id}/thread.
  • An empty list is a real answer: most posts have no replies. It is cross-checked against the scraper pool before being reported, so an empty list here means empty rather than 'we could not ask'.
  • Pagination is an opaque cursor: pass next_cursor back as ?cursor= and stop when has_next_page is false. Cursors are X's own and expire; treat them as good for the next call, not as a bookmark to store.
  • Metered as a live call. It leaves the building and spends a slot on the same scraper pool that lets sellers verify a listing, so read GET /scrape/status and back off BEFORE you start failing rather than after.
  • 503 with upstream_error or upstream_timeout is worth retrying; 404 is not. A 503 whose message names a rate-limited X endpoint means the answer is unknown, not empty - never cache it as a result.

Parameters

Every value the call accepts, with the example the spec ships so the request runs as written.

NameInRequiredExampleWhat it does
idpathrequired440322224407314432Numeric post id - the digits at the end of an x.com/.../status/... link.
limitqueryoptional20Rows in this page, 1-100. The ceiling is the service's, not yours: asking for more returns the ceiling rather than an error.
cursorqueryoptional-Opaque token from a previous response's next_cursor.

Call it

Authenticate with a bearer token or the x-api-key header. Keys are server-to-server credentials. Never embed one in front-end code - call the API from your own backend and forward the result.

curl
curl "https://crmsolid.com/data-api/v2/x/tweets/440322224407314432/replies" \
  -H "Authorization: Bearer psk_live_..."
JavaScript
const res = await fetch("https://crmsolid.com/data-api/v2/x/tweets/440322224407314432/replies", {
  headers: {
    Authorization: `Bearer ${process.env.CRM_SOLID_DATA_API_KEY}`,
  },
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${error.code}: ${error.message} (${error.request_id})`);
}

const { data, meta } = await res.json();
Python
import os

import requests

res = requests.get(
    "https://crmsolid.com/data-api/v2/x/tweets/440322224407314432/replies",
    headers={"Authorization": f"Bearer {os.environ['CRM_SOLID_DATA_API_KEY']}"},
    timeout=30,
)
res.raise_for_status()

payload = res.json()
data, meta = payload["data"], payload["meta"]

Keys look like psk_live_... for production keys, psk_test_... for test keys and are minted in the panel.

What comes back

Success is { data, meta }. Failure is { error: { code, message, request_id } }. The body below is the spec's own example: the values in it are illustrative readings, not live numbers.

Tweets
1 items
200 GET /x/tweets/{id}/replies
{
  "data": {
    "tweets": [
      {
        "tweet_id": "1908244251923312641",
        "url": "https://x.com/elonmusk/status/1908244251923312641",
        "text": "Starship is stacked",
        "created_at": "2026-08-30T16:02:11+00:00",
        "lang": "en",
        "source": "Twitter for iPhone",
        "likes": 184221,
        "retweets": 21004,
        "replies": 9118,
        "quotes": 1402,
        "bookmarks": 3889,
        "views": 41882337,
        "is_reply": false,
        "is_retweet": false,
        "is_quote": false,
        "conversation_id": "1908244251923312641",
        "in_reply_to_tweet_id": null,
        "quoted_tweet_id": null,
        "retweeted_tweet_id": null,
        "hashtags": [],
        "mentions": [],
        "links": [],
        "media": [
          "photo"
        ],
        "author": {
          "user_id": "44196397",
          "handle": "elonmusk",
          "display_name": "Elon Musk",
          "bio": "",
          "followers": 221400112,
          "following": 1104,
          "tweets": 78412,
          "media_count": 9233,
          "likes_given": 148902,
          "is_verified": false,
          "is_blue_verified": true,
          "is_protected": false,
          "location": null,
          "avatar_url": "https://pbs.twimg.com/profile_images/1234567890/abc_400x400.jpg",
          "header_url": null,
          "created_at": "2009-06-02T20:12:29+00:00",
          "profile_url": "https://x.com/elonmusk"
        }
      }
    ]
  },
  "meta": {
    "request_id": "req_9f2c41a8b3d5",
    "generated_at": "2026-08-23T09:14:02.317Z",
    "took_ms": 42,
    "page": {
      "limit": 50,
      "next_cursor": "eyJrIjoiMTczNDU2IiwiZCI6ImEifQ",
      "count": 50
    },
    "cache_age_s": 0
  }
}

The meta block

  • request_idstringrequired

    Unique id for this request. Quote it in a support ticket.

  • generated_atstringrequired

    Server time the response was produced.

  • took_msintegerrequired

    Milliseconds spent server-side.

  • pagePageoptional
  • sourcestringoptional

    Which backend served the payload, for endpoints with more than one.

  • cache_age_sintegeroptional

    Age of the underlying data in seconds. 0 for live reads.

meta.page

  • limitintegerrequired

    Rows requested. Default 50, maximum 500.

  • next_cursorstringrequired

    Pass as ?cursor= to fetch the next page. null means the result set is exhausted, and it is the only reliable stop condition.

  • countintegerrequired

    Rows in this page.

  • totalintegeroptional

    Total matching rows. Present only when counting is cheap; never assume it is there.

List endpoints take ?limit= (max 500) and ?cursor=. Follow meta.page.next_cursor until it is null; cursors are opaque and signed.

When it fails

GET /x/tweets/{id}/replies documents 8 failure statuses. Branch on error.code, which is stable and enumerated; message is prose and may change.

  • 401Unauthorizedunauthorized | invalid_key

    No key was presented, or the key is unknown, revoked or expired.

  • 402PaymentRequiredpayment_required | subscription_inactive

    The key is valid but the plan behind it cannot serve the call: the included requests are spent and overage is switched off, capped or unfunded (payment_required), or the billing period lapsed and was not renewed (subscription_inactive). Retrying does not help; paying does. The X-Plan-* headers on this response say how far past the line you are.

    Carries X-Plan, X-Plan-Limit, X-Plan-Overage, X-Plan-Period-End, X-Plan-Remaining.

  • 403Forbiddenforbidden_scope | forbidden_ip

    The key is valid but not allowed to make this call: it lacks the scope, or the request came from an address outside the key's allowlist.

  • 404NotFoundnot_found

    The addressed resource does not exist.

  • 422InvalidRequestinvalid_request

    A parameter is malformed, out of range or mutually exclusive with another. `details` names the offending fields.

  • 429RateLimitedrate_limited | quota_exceeded

    Either the burst ceiling for the current minute or the daily quota is spent. Distinguish with the code: rate_limited clears within the minute, quota_exceeded does not clear until 00:00 UTC.

    Carries Retry-After, X-Quota-Limit, X-Quota-Remaining, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-Request-Id.

  • 500InternalErrorinternal_error

    Something failed on our side. Internals are never leaked; quote the request id.

  • 503Unavailableupstream_timeout | upstream_error | not_configured

    The request could not be served right now. BRANCH ON error.code, not on the status: 'upstream_timeout' means a source was too slow (this is what a catalog query hitting its 15-second statement timeout returns, so it is reachable from any endpoint that reads the corpus, not only the live-scrape ones) and the same call is worth retrying with backoff - narrowing it with a smaller limit, a filtered scope or a less popular account makes it far less likely; 'upstream_error' means a source was unreachable, so back off further; 'not_configured' means the capability has no backing service in this deployment, and retrying will never help.

Every response carries X-Request-Id and meta.request_id. Quote it in support requests.

Coverage and limits

This endpoint covers X. Rate limits come from the tier on your key.

X
TierRequests a minuteRequests a dayLive reads a minute
free301,0005
standard12025,00020
pro600250,00060
unlimited6,00010,000,000600

Live reads count against the live column as well as the ordinary one, so a burst of them runs out of the live bucket first. Every response reports where you stand in X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset and the X-Plan headers.

Start calling it

A key takes a minute to mint in the panel, no card. The reference covers authentication, the envelope, scopes, rate limits and every error code in one page.

Reference path: /data-api/reference/x-tweets-replies

We value your privacy

We use cookies to improve our site, analyze traffic, and personalize ads. You can accept all, reject non-essential, or customize your choices. Read our Cookie Policy.