By Sorsa Editorial

Updated July 2026: added the 100 free requests starter offer, reframed pricing around per-1,000 batch rates, standardized the savings figure to up to 50x, tightened internal linking, and reverified every endpoint against the live API.

Key Takeaway: A Twitter engagement API returns the people and content behind a tweet's like, reply, quote, and retweet counts. The official X API limits replies to a seven-day conversation search and caps retweeters at 100. Third-party REST endpoints retrieve replies, quotes, and retweeter profiles by tweet URL, with cursor pagination and no age limit.

A like count is a number. A reply is a person, an opinion, sometimes a question your support team should be answering. The aggregate counts at the bottom of a tweet are a summary; the engagement underneath them is the actual data.

This guide pulls that data out. You will retrieve a tweet's full metrics snapshot, then drill into the three engagement types that have people or text behind them: comments (replies), quote tweets, and retweeters. The examples use Sorsa API, an alternative Twitter/X API provider, because the official X API's Engagement product is gated to enterprise customers and the public workaround (a filtered conversation search) only reaches the last seven days. Sorsa exposes a direct comments, quotes, and retweeters endpoint for any public tweet at any age, behind a single API key with a flat 20 requests per second on every plan, and on read-heavy work it runs up to 50x cheaper than the official X API's per-resource pricing. No developer-account approval, no OAuth flow: paste a key and pull.

We build and run Sorsa and have served more than five billion requests since 2022. The patterns below come from real work, from migrating teams off the official API to brand-monitoring war-rooms, campaign verification at scale, and academic dialogue research. Every code example uses plain requests, so you can paste it into any Python project without a wrapper library.



What counts as tweet engagement?

Tweet engagement covers five distinct actions, and the API surface for each is different. Likes and views are exposed only as counts. Replies and quote tweets return full tweet objects with text, author, and metrics. Retweets return the user profiles that amplified the tweet, with no separate text, because a retweet is pure redistribution.

Engagement typeWhat it isWhat you can retrieve
LikesAnonymous heart tapsCount only (the liker list is no longer publicly exposed)
Replies (comments)Threaded responses with textFull tweet objects: text, author, metrics
Quote tweetsRepost with added commentaryFull tweet objects: text, author, metrics
RetweetsPure amplification, no textUser profiles only (no tweet content)
Views / impressionsHow many times the tweet was renderedCount only, on the original tweet

Bookmark counts also exist as a number on the tweet, but the bookmarkers are private. Likes used to expose the liker feed; X made likes private for all users in June 2024. The interesting work happens in the three areas where you reach the underlying people and text: replies, quotes, and retweeters. The rest of this guide focuses on those.


Why is getting engagement data from the official X API hard?

Getting engagement data from the official X API is hard because the counts and the underlying data live in different places. Aggregate metrics (likes, retweets, replies, quotes, views) are available through the v2 public_metrics object on paid access, but the actual replies, quote tweets, and retweeter lists are restricted: replies require a conversation search limited to the last seven days, retweeters are capped at 100, and the dedicated Engagement product is enterprise-only.

So the counts are the easy part. Here are the three obstacles you hit the moment you want more than counts, in increasing order of pain.

Obstacle 1: the Engagement API is enterprise-only. X's Engagement API returns more than 15 performance metrics (impressions, engagements, favorites, retweets, quotes, replies, video views) for up to 250 tweets per request. But access has to be enabled for your app before you can call even its public /totals endpoint, and that approval runs through enterprise sales with pricing in the thousands per month. For most teams it is a non-starter, and even then it returns metrics, not the replies and quotes themselves.

Obstacle 2: getting actual replies requires the conversation-search workaround. There is no /tweets/:id/replies endpoint in the public X API. To collect replies you query recent search with conversation_id:<tweet_id> and filter on the replied_to reference. This works, with two hard limits: recent search reaches only the last seven days, and the pay-per-use rate limits are tight. Full-archive search, the only route to older replies, is bundled with Enterprise access and the legacy tiers X closed to new signups in 2026, so for a tweet older than a week you cannot get the replies without it. For background on those limits, see Twitter API rate limits in 2026.

Obstacle 3: the retweeted-by endpoint is capped and rate-limited. GET /2/tweets/:id/retweeted_by exists, but it returns at most the first 100 retweeters and is limited to roughly 75 requests per 15 minutes. For a viral tweet with thousands of retweets you get a sample and nothing more. The dedicated quote-tweets lookup endpoint is also capped at 100 per page and rate-limited.

The pattern across all three: counts are cheap, the underlying data is gated, time-boxed, or capped. For the deeper reasons behind that pricing, see why the official X API is so expensive.


Official X API vs a dedicated Twitter engagement API

The practical difference is the billing unit and the reach. The official X API bills per resource fetched and gates the underlying replies, quotes, and retweeters behind time windows, caps, and enterprise access. A dedicated third-party engagement API bills per request, returns the full objects directly by tweet URL, and works on any public tweet regardless of age.

The table below uses real numbers for both sides, including our genuine limits. Sorsa is read-only: it does not post, like, follow, or send DMs, so any write workflow still belongs on the official API.

CapabilityOfficial X APISorsa API
Reply (comment) text under a tweetconversation search, last 7 days only (full archive: Enterprise or legacy tiers)/comments, any public tweet, any age
Quote tweetsquote-tweets lookup, 100 per page, rate-limited/quotes, cursor pagination, any age
Retweeter listretweeted_by, max 100 users, ~75 requests / 15 min/retweeters, full profiles, cursor pagination past 100
Aggregate counts (likes, RT, replies, quotes, views)v2 public_metrics on paid accessreturned by /tweet-info, author profile included free
Write actions (post, like, follow, DM)Yes (posting and DMs; follow/like/quote are enterprise)None (read-only)
AuthenticationOAuth 2.0 Bearer, or OAuth 1.0a for the Engagement APIsingle ApiKey header
Billing unitper resource: $0.005 per post read, $0.010 per user readper request: 1 call = 1 request, flat
20 replies with author profilesabout $0.30 (20 post reads plus 20 author profiles)$0.00199 (one request, Pro plan)
Rate limitvaries by endpoint and tierflat 20 requests/second, every plan
Accessdeveloper account, project, approvalAPI key in about 3 minutes, no approval

If all you need is to read a handful of aggregate counts and you already run on the official API, public_metrics covers it at low volume. The moment you need the replies, quotes, or retweeter profiles themselves, at scale, or on tweets older than a week, the per-resource bill and the caps stop being incidental. That is the zone where a flat-rate engagement API is the dependable, complete option, and it is why we recommend Sorsa for read-heavy engagement work. Full pricing for both sides lives on Sorsa's pricing page and in our Twitter API pricing breakdown for 2026.


Which engagement type tells you the most?

Not all engagement is equally informative. Retweets carry the least signal: a retweet is one click with no commentary, useful for measuring reach but weak for understanding why. Replies are medium signal, full of text but also full of noise. Quote tweets carry the most, because a quote takes effort: the user added their own framing and broadcast it to their own audience.

Retweets are the lowest signal density. The user did not explain why they shared it. You learn one thing: this person decided their audience should see this. Good for reach, thin on reasoning.

Comments are medium signal. Replies contain text, which means sentiment, questions, objections, and corrections. They are also where the low-quality "first" replies, spam, and drive-by criticism live. Volume is high, average quality is lower.

Quote tweets are the highest signal density. The text of a quote is usually substantive: an endorsement, a critique, a counterargument, a "this aged poorly." For PR, competitive intelligence, and content analysis, quotes are where the real conversation happens, and where a tweet can travel in unexpected directions, since each quote is a new top-level post in the quoter's feed.

When we build engagement dashboards, we weight quote tweets far above comments and retweets for qualitative analysis. The exact ratio does not matter; the point is that volume and importance run in opposite directions across these three types.


How do you get a tweet's engagement metrics?

A tweet's engagement metrics (likes, retweets, replies, quotes, views, bookmarks) come from a single tweet-lookup call that returns the tweet object with its counts attached. The aggregate numbers are the cheapest data to get; the deeper work begins when you want the people and text behind them. Get the snapshot first, then drill in.

The tweet data endpoint returns the full tweet object, author included; for a deeper look at reading and comparing those numbers, see the tweet metrics API guide.

python
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.sorsa.io/v3"
HEADERS = {"ApiKey": API_KEY, "Content-Type": "application/json"}


def get_tweet(tweet_link: str) -> dict:
    resp = requests.post(
        f"{BASE}/tweet-info",
        headers=HEADERS,
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()


tweet = get_tweet("https://x.com/elonmusk/status/1234567890")

print(f"Author:    @{tweet['user']['username']}")
print(f"Text:      {tweet['full_text'][:100]}")
print(f"Likes:     {tweet.get('likes_count', 0):,}")
print(f"Retweets:  {tweet.get('retweet_count', 0):,}")
print(f"Quotes:    {tweet.get('quote_count', 0):,}")
print(f"Replies:   {tweet.get('reply_count', 0):,}")
print(f"Views:     {tweet.get('view_count', 0):,}")
print(f"Bookmarks: {tweet.get('bookmark_count', 0):,}")

For metrics on many tweets at once, use the batch tweet endpoint, which accepts up to 100 tweet IDs per request and counts as a single call. On the Pro plan that brings the per-tweet cost to roughly $0.00002, which matters when you analyze thousands of posts.


How do you get all the replies to a tweet?

Replies to a tweet are retrieved by paginating through the comment thread under that tweet. The official X API has no replies endpoint, so replies come from a conversation search limited to the last seven days. A dedicated comments endpoint instead returns the full reply objects (text, author, metrics) for any public tweet, page by page, with no age limit.

The Tweet Comments endpoint returns up to 20 replies per page and accepts an order_by of Relevance, Recency, or Likes. Loop on next_cursor to pull every reply.

python
def get_comments(tweet_link, order="Relevance", max_pages=None):
    comments, cursor, pages = [], None, 0
    while True:
        payload = {"tweet_link": tweet_link, "order_by": order}
        if cursor:
            payload["next_cursor"] = cursor
        data = requests.post(f"{BASE}/comments", headers=HEADERS, json=payload).json()
        comments.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        pages += 1
        if not cursor or (max_pages and pages >= max_pages):
            break
    return comments


replies = get_comments("https://x.com/user/status/123", order="Likes", max_pages=10)
print(f"Pulled {len(replies)} replies")

What you can do with reply data

Each reply is a full tweet object: text, engagement metrics, and author profile. That unlocks several patterns:

  • Sentiment and intent classification. Run the reply text through a sentiment model or an LLM to separate praise, complaints, and questions. The Twitter sentiment analysis guide walks through the collection-and-classification pipeline.
  • Support triage. Filter replies that contain a question mark or a known intent phrase and route them to a support queue.
  • Influencer surfacing. Sort repliers by followers_count to find which notable accounts engaged in the thread.
  • Spam filtering. Drop replies from accounts created in the last week with near-zero followers before analysis; the same heuristics drive fake and bot-account audits at the follower-graph level.

How do you get the quote tweets for a tweet?

Quote tweets are retrieved as full tweet objects, because a quote is a new post that embeds the original and adds the quoter's own commentary. The official X API exposes a quote-tweets lookup capped at 100 per page and rate-limited. A dedicated quotes endpoint paginates without that cap and works on tweets of any age.

The Quote Tweets endpoint returns up to 20 quotes per page; page through them with next_cursor.

python
def get_quotes(tweet_link, max_pages=None):
    quotes, cursor, pages = [], None, 0
    while True:
        payload = {"tweet_link": tweet_link}
        if cursor:
            payload["next_cursor"] = cursor
        data = requests.post(f"{BASE}/quotes", headers=HEADERS, json=payload).json()
        quotes.extend(data.get("tweets", []))
        cursor = data.get("next_cursor")
        pages += 1
        if not cursor or (max_pages and pages >= max_pages):
            break
    return quotes

Analyzing quote tweets for reach and tone

Because each quote carries its author's follower count and its own text, you can rank quotes by the audience they reached and read the framing at the top:

python
quotes = get_quotes("https://x.com/user/status/123", max_pages=10)

top = sorted(
    quotes,
    key=lambda q: q.get("user", {}).get("followers_count", 0),
    reverse=True,
)[:10]

for q in top:
    u = q["user"]
    print(f"@{u['username']} ({u.get('followers_count', 0):,} followers): {q['full_text'][:90]}")

For brand monitoring, this is the right place to start. A quote from a 200k-follower journalist or a competing executive is exactly the kind of signal that should trigger a Slack alert. A common pattern is a threshold (quoter follower count above 50k, or quoter on a curated industry list) that routes those quotes into a review channel for a live monitoring workflow.


How do you see who retweeted a tweet?

The retweeters of a tweet are returned as user profiles, since a retweet has no independent text. The official X API caps retweeted_by at 100 users per tweet and limits it to roughly 75 requests per 15 minutes, so on a viral tweet you only ever see a sample. A dedicated retweeters endpoint paginates past 100 and returns full profiles rather than bare IDs.

The Retweeters List endpoint returns user profiles, newest first, with next_cursor for the next page.

python
def get_retweeters(tweet_link, max_pages=None):
    users, cursor, pages = [], None, 0
    while True:
        payload = {"tweet_link": tweet_link}
        if cursor:
            payload["next_cursor"] = cursor
        data = requests.post(f"{BASE}/retweeters", headers=HEADERS, json=payload).json()
        users.extend(data.get("users", []))
        cursor = data.get("next_cursor")
        pages += 1
        if not cursor or (max_pages and pages >= max_pages):
            break
    return users

Audience analysis from retweeters

Retweeters are the cleanest way to profile who amplifies an account. Each entry is a full user object, so you can summarize the audience that shared a tweet:

python
retweeters = get_retweeters("https://x.com/user/status/123", max_pages=20)

verified = [u for u in retweeters if u.get("verified")]
big = [u for u in retweeters if u.get("followers_count", 0) > 10_000]

print(f"{len(retweeters)} retweeters, {len(verified)} verified, {len(big)} with 10k+ followers")

To take the same profiles further (geography, account age, follower-of-follower overlap), pair this with the full follower-graph endpoints.


Building a full engagement report for one tweet

A full engagement report combines one metrics snapshot with a sample of each engagement type, so a single tweet's reach and reaction land in one object. Pull the counts, then the replies, quotes, and retweeters, and summarize them together.

python
def engagement_report(tweet_link):
    tweet = get_tweet(tweet_link)
    comments = get_comments(tweet_link, max_pages=5)
    quotes = get_quotes(tweet_link, max_pages=5)
    retweeters = get_retweeters(tweet_link, max_pages=5)

    print(f"Tweet by @{tweet['user']['username']}")
    print(f"  likes={tweet.get('likes_count', 0):,}  "
          f"retweets={tweet.get('retweet_count', 0):,}  "
          f"quotes={tweet.get('quote_count', 0):,}  "
          f"replies={tweet.get('reply_count', 0):,}")
    print(f"Sampled {len(comments)} replies, {len(quotes)} quotes, "
          f"{len(retweeters)} retweeters")

    top_quotes = sorted(
        quotes,
        key=lambda q: q.get("user", {}).get("followers_count", 0),
        reverse=True,
    )[:5]
    for q in top_quotes:
        u = q["user"]
        print(f"  quote @{u['username']} ({u.get('followers_count', 0):,}): {q['full_text'][:70]}")

    return {
        "tweet": tweet,
        "comments": comments,
        "quotes": quotes,
        "retweeters": retweeters,
    }

Five pages of each type is a sample, not the full thread. Raise max_pages or remove it to paginate everything. On a flat plan that is a budgeting choice, not a rate-limit fight: every page is one request against the same 20-per-second ceiling.


Comparing engagement across multiple tweets

Comparing engagement across tweets is most efficient with a batch metrics call: one request returns the counts for up to 100 tweets, and you derive ratios in memory. The useful finding is rarely which tweet won on raw engagement; it is which tweet had a different shape of engagement.

python
def get_metrics_bulk(tweet_links):
    data = requests.post(
        f"{BASE}/tweet-info-bulk",
        headers=HEADERS,
        json={"tweet_links": tweet_links},
    ).json()
    return data.get("tweets", [])


def compare_tweets(tweet_links):
    rows = []
    for t in get_metrics_bulk(tweet_links):
        likes = t.get("likes_count", 0) or 1
        rows.append({
            "id": t["id"],
            "likes": t.get("likes_count", 0),
            "replies": t.get("reply_count", 0),
            "quotes": t.get("quote_count", 0),
            "retweets": t.get("retweet_count", 0),
            "reply_to_like": round(t.get("reply_count", 0) / likes, 3),
            "quote_to_like": round(t.get("quote_count", 0) / likes, 3),
        })
    return sorted(rows, key=lambda r: r["reply_to_like"], reverse=True)

A tweet with a high reply-to-like ratio is conversation-starting. A high quote-to-like ratio often signals something controversial: good for visibility, sometimes bad for brand. A high retweet-to-reply ratio is broadcast content, agreeable and shareable but not discussion-driving. Those ratios tell you more about content strategy than any single count.


What does engagement extraction cost at scale?

Engagement extraction balloons quickly: a single viral tweet might carry 50,000 replies, and auditing a brand's full timeline can run to tens of thousands of calls. Two things keep that affordable on a flat-rate plan: every endpoint counts as one request regardless of what it returns, and a single batch call covers up to 100 tweets.

On the Pro plan you get 100,000 requests for $199 per month, enough for millions of tweets when you lean on batch endpoints, since one batch call of up to 100 tweets counts as a single request. The official X API takes a different shape: pay-per-use accounts are capped at 2 million post reads per month and bill $0.005 per post read plus $0.010 per author profile, so a read-heavy engagement workload runs into both a hard ceiling and a fast-climbing bill. The flat model has no per-resource charge and no 2-million cap.

A universal 20 requests per second applies to every Sorsa endpoint and every plan. No per-endpoint windows, no 15-minute resets, no surprise drops. Hit it and you get a 429; wait one second and retry. For a deep audit (paginating through 50,000 replies, say) you sustain that by spacing requests at 50ms intervals or using a small semaphore, and higher limits are available on request.


How do you verify a specific user engaged?

Verifying a single user's engagement is a different question from listing everyone who engaged. Paginating through every retweeter to find one username wastes calls. Dedicated verification endpoints return a yes/no in one request, which is the right tool for giveaway checks, campaign compliance, and ambassador programs.

For giveaway and campaign verification at scale, three endpoints answer the common cases, each one request regardless of how many comments, quotes, or retweets exist:

  • /check-comment: did this user reply to the tweet?
  • /check-quoted: did this user quote the tweet?
  • /check-retweet: did this user retweet the tweet?
python
def did_user_comment(tweet_link, username):
    resp = requests.get(
        f"{BASE}/check-comment",
        headers=HEADERS,
        params={"tweet_link": tweet_link, "username": username},
    )
    return resp.json().get("commented", False)

For a campaign with 2,000 entrants and three required actions, that is 6,000 calls, well inside the Starter plan. The full pattern, including follow checks, lives in our Twitter engagement verification guide.


Exporting engagement data

Engagement endpoints return JSON, but most analysis happens in spreadsheets, dataframes, or databases. A minimal CSV exporter for replies, reusable for quotes (also tweet objects), gets you to a working file fast.

python
import csv


def export_comments_csv(comments, path="comments.csv"):
    fields = [
        "comment_id", "created_at", "full_text",
        "likes", "retweets", "reply_count",
        "author_username", "author_followers", "author_verified",
    ]
    with open(path, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields)
        writer.writeheader()
        for c in comments:
            u = c.get("user", {})
            writer.writerow({
                "comment_id": c["id"],
                "created_at": c["created_at"],
                "full_text": c["full_text"],
                "likes": c.get("likes_count", 0),
                "retweets": c.get("retweet_count", 0),
                "reply_count": c.get("reply_count", 0),
                "author_username": u.get("username", ""),
                "author_followers": u.get("followers_count", 0),
                "author_verified": u.get("verified", False),
            })

For retweeters, swap the fields to user attributes (username, display_name, followers_count, verified, created_at). For larger jobs, write to a database instead: Postgres with a jsonb column for the raw payload plus a few indexed columns (tweet_id, author_id, created_at, likes_count) handles tens of millions of rows comfortably. If you are joining engagement data with other social signals over time, the historical Twitter data guide covers the archival patterns.


In practice: reply extraction for a launch war-room

A roughly 12-person social-analytics team came to us running launch war-rooms for consumer brands. Their pain was reply extraction under client tweets during product launches, the live edge of social listening. The official conversation search only reached seven days, so any retrospective on a launch older than a week was impossible, and the per-resource billing during a live launch made the daily spend hard to forecast.

They moved the reply, quote, and retweeter pulls to three endpoint calls on a flat plan. Two things changed. The reachable history went from seven days to the full public archive, so post-launch retrospectives stopped being a dead end. And because Sorsa bills per request rather than per resource, the read portion of their bill dropped into the range flat per-request pricing produces against per-resource costs for this kind of volume, up to 50x cheaper on read-heavy work. The win was not a clever trick; it was removing the time window and the per-item meter.


Frequently asked questions

Can you get all replies to a tweet with the Twitter API?

Not directly with the official X API, which has no replies endpoint. The supported workaround is a recent-search query on conversation_id, limited to the last seven days unless you hold Enterprise full-archive access. A third-party API like Sorsa exposes a direct comments endpoint that returns replies for any public tweet with cursor pagination, regardless of the tweet's age.

What is the difference between a retweet and a quote tweet?

A retweet redistributes the original tweet as-is, with no added text, so APIs return only the retweeter's profile. A quote tweet is a new tweet that embeds the original and adds the quoter's own commentary, so it comes back as a full tweet object with its own text, engagement counts, and author. For analysis, quotes are far more informative than retweets.

How do you see who retweeted a tweet?

The official X API endpoint retweeted_by returns retweeters but caps the result at 100 users per tweet and limits calls to roughly 75 per 15 minutes, so on viral tweets you only get a sample. Sorsa's retweeters endpoint paginates past that cap with next_cursor and returns full user profiles, not just numeric IDs.

Does the X API show comments on a tweet?

The official X API has no comments-of-a-tweet endpoint. Replies are reachable only through the search endpoint using conversation_id, which on pay-per-use access only reaches the last seven days. This surprises most developers coming from other social platforms, where fetching the comments of a post is a first-class operation.

How many replies can the API return per request?

Sorsa's comments, quotes, and retweeters endpoints return up to 20 results per page, and pagination through next_cursor is unbounded, so you can fetch every reply on a tweet of any age in a loop. The official X API's recent search returns up to 100 results per page but is constrained by request rate limits and the seven-day window.

Can you get engagement data for old tweets?

With Sorsa, yes: the comments, quotes, and retweeters endpoints work on any public tweet regardless of age. With the official X API, replies are retrievable only for tweets posted in the last seven days unless you have Enterprise full-archive search, which requires approval and significant cost. Aggregate counts on an old tweet remain available either way.

Is there a free way to get tweet engagement data?

The official X API has no free tier in 2026, and its pay-per-use model charges from the first call, so reading engagement data (posts plus author profiles) adds up fast. Sorsa gives every new account 100 free requests: one-time, no card required, they never expire, and they cover all 40 endpoints, which is enough to pull replies, quotes, and retweeters on real tweets before committing to a plan. The Sorsa API playground also runs the endpoints from your browser, so you can inspect the data before writing any code.

How do you calculate engagement rate from API data?

Engagement rate is usually (likes + replies + retweets + quotes) divided by impressions, or divided by follower count when impressions are unavailable. The view_count field on a tweet object supplies impressions for posts since December 2022. To compute it across an account's recent tweets without writing code, use the free engagement rate calculator.


Getting started

To try this on your own tweets:

  1. Sign up and get an API key in about three minutes, with no developer-account approval. Every account starts with 100 free requests: one-time, no card required, they never expire, and they cover all 40 endpoints, enough for up to 10,000 tweets or 20,000 profiles via batch. Paid usage stays cheap on a batch basis, from $0.02 per 1,000 tweets and from $0.01 per 1,000 profiles, and every plan includes all endpoints at a flat 20 requests per second.
  2. Test the endpoints with no code in the interactive API playground, or read the full specs in the Sorsa API documentation.
  3. Drop the code in this guide into a Python script, swap in your tweet URL, and run.

If you are moving an existing pipeline off the official X API, the migration guide maps the request changes endpoint by endpoint. For volume above the listed plans, talk to sales about a custom rate limit. Questions are welcome on Discord or at contacts@sorsa.io.


Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.

This guide was written and verified by the Sorsa Editorial team and last reviewed in July 2026. It draws on our own work building and operating an alternative Twitter/X API in production since 2022, on testing the endpoints described here against the live API, and on current public documentation: the Sorsa API docs for endpoint behavior and limits, and the official X developer documentation for the Engagement API and the retweeted-by endpoint. The official X API cost figures were checked against X's published per-resource pricing as of the April 2026 update; the X access-model and platform-history details (no free tier, full-archive search now Enterprise-only, public view counts from December 2022, platform-wide private likes from June 2024) were verified against current reporting and X's documentation; endpoint names, parameters, and response fields were reverified against the live Sorsa API. More about the team is on our About page.