Skip to main content

API Response Format: User and Tweet Object Schemas

Sorsa API returns all data as JSON. This page documents the response structure, core data objects, field types, and pagination model so you know exactly what to expect from every endpoint.

Conventions

Before diving into specific objects, here are the formatting rules that apply across the entire API. IDs are strings. All X/Twitter IDs (id, conversation_id_str, in_reply_to_tweet_id, etc.) are returned as strings, not integers. X uses Snowflake IDs, which are 64-bit numbers that exceed JavaScript’s Number.MAX_SAFE_INTEGER. Returning them as strings prevents silent precision loss in browsers, Node.js, and any language that represents JSON numbers as floating-point. Timestamps are ISO 8601 strings. All date fields use the format 2026-03-06T12:00:00Z. This is compatible with standard datetime parsers in every major language and database. Booleans are strict. Status flags like verified, is_reply, protected, and can_dm are always true or false, never 0/1 or "true"/"false". Null and missing fields. Optional fields that have no value are returned as null. Fields like bio_urls or pinned_tweet_ids return null rather than an empty array when there is no data.

Response wrappers

Endpoints that return a single object (like /info or /tweet-info) return the object directly at the top level. Endpoints that return lists use one of the following wrapper structures. UsersResponse - used by /followers, /follows, /verified-followers, /retweets, /search-users, /list-members, /list-followers, /community-members
{
  "users": [ ... ],
  "next_cursor": "abc123"
}
TweetsResponse - used by /user-tweets, /comments, /quotes, /search-tweets, /mentions, /list-tweets, /community-tweets, /community-search-tweets
{
  "tweets": [ ... ],
  "next_cursor": "abc123"
}
FollowersResponse - used by /new-followers-7d, /new-following-7d, /top-followers, /top-following
{
  "users": [ ... ]
}
Note: FollowersResponse does not include next_cursor. It returns the full result set in a single response.

The User object

The User object represents an X/Twitter account profile. It is returned directly by /info, as an array element in list endpoints, and nested inside every Tweet object as the user field.
{
  "id": "44196397",
  "username": "elonmusk",
  "display_name": "Elon Musk",
  "description": "Mars & Cars, Chips & Dips",
  "location": "Earth",
  "created_at": "Tue Jun 02 20:12:29 +0000 2009",
  "followers_count": 236021252,
  "followings_count": 1292,
  "favourites_count": 214650,
  "tweets_count": 98479,
  "media_count": 4374,
  "profile_image_url": "https://pbs.twimg.com/profile_images/.../photo_normal.jpg",
  "profile_background_image_url": "https://pbs.twimg.com/profile_banners/44196397/...",
  "bio_urls": ["https://example.com"],
  "pinned_tweet_ids": ["2028500984977330453"],
  "verified": true,
  "can_dm": false,
  "protected": false,
  "possibly_sensitive": false
}
FieldTypeDescription
idstringPermanent numeric user ID (Snowflake)
usernamestringCurrent handle / screen name (without @)
display_namestringPublic profile name
descriptionstringAccount bio
locationstringUser-specified location (free text)
created_atstringAccount creation timestamp
followers_countintegerNumber of followers
followings_countintegerNumber of accounts followed
favourites_countintegerTotal likes given by this account
tweets_countintegerTotal tweets posted
media_countintegerTotal media items posted
profile_image_urlstringAvatar image URL
profile_background_image_urlstringBanner image URL
bio_urlsarray of strings or nullURLs from the bio section
pinned_tweet_idsarray of strings or nullIDs of pinned tweets
verifiedbooleanVerification status (Blue, Gold, or Gray checkmark)
can_dmbooleanWhether DMs are open
protectedbooleanWhether the account is private
possibly_sensitivebooleanWhether the account is flagged as sensitive

The Follower object

The Follower object extends the User object with one additional field. It is returned by Sorsa Info endpoints like /new-followers-7d, /top-followers, etc.
Additional fieldTypeDescription
followerDatestringDate when the follow relationship was recorded

The Tweet object

The Tweet object contains the full content, metadata, engagement metrics, and nested relationships for a single tweet. It is returned directly by /tweet-info and as array elements in tweet list endpoints.
{
  "id": "1234567890123456789",
  "full_text": "This is the complete tweet text including mentions and links",
  "created_at": "2026-03-06T12:00:00Z",
  "lang": "en",
  "bookmark_count": 42,
  "likes_count": 1500,
  "quote_count": 23,
  "reply_count": 89,
  "retweet_count": 312,
  "view_count": 250000,
  "conversation_id_str": "1234567890123456789",
  "in_reply_to_tweet_id": null,
  "in_reply_to_username": null,
  "is_reply": false,
  "is_quote_status": false,
  "is_replies_limited": false,
  "entities": [ ... ],
  "user": { ... },
  "quoted_status": null,
  "retweeted_status": null
}
Content fields
FieldTypeDescription
idstringUnique tweet ID (Snowflake)
full_textstringComplete tweet text
created_atstringPublication timestamp
langstringDetected language code (e.g., “en”, “ja”, “es”)
Engagement metrics
FieldTypeDescription
likes_countintegerTotal likes
retweet_countintegerTotal retweets
reply_countintegerTotal replies
quote_countintegerTotal quote tweets
view_countintegerTotal impressions
bookmark_countintegerTotal bookmarks
Thread and reply context
FieldTypeDescription
conversation_id_strstringID of the root tweet in the thread
in_reply_to_tweet_idstring or nullID of the tweet this is replying to
in_reply_to_usernamestring or nullUsername of the account being replied to
is_replybooleanWhether this tweet is a reply
is_quote_statusbooleanWhether this tweet quotes another tweet
is_replies_limitedbooleanWhether replies are restricted by the author
Nested objects
FieldTypeDescription
userUser objectFull profile of the tweet author
entitiesarray of TweetEntityMedia and link attachments
quoted_statusTweet object or nullThe quoted tweet (full object, recursive)
retweeted_statusTweet object or nullThe original retweeted tweet (full object, recursive)
The quoted_status and retweeted_status fields contain complete Tweet objects, including their own user, entities, and engagement metrics. This means you get all related data in a single API call without needing to make follow-up requests.

The TweetEntity object

Each item in the entities array represents a media attachment or embedded link within a tweet.
{
  "type": "photo",
  "link": "https://pbs.twimg.com/media/..._large.jpg",
  "preview": "https://pbs.twimg.com/media/..._small.jpg"
}
FieldTypeDescription
typestringEntity type (e.g., photo, video, animated_gif)
linkstringDirect URL to the full-resolution asset
previewstringPreview text or thumbnail URL

Cursor-based pagination

Endpoints that return lists use cursor-based pagination. This approach is more reliable than offset-based pagination for dynamic feeds where new content is constantly being added. How it works:
  1. Send your initial request without a cursor.
  2. The response includes a next_cursor field along with the data.
  3. To fetch the next page, include the next_cursor value in your next request.
  4. When next_cursor is null or absent, you have reached the end of the data.
GET endpoints accept the cursor as a query parameter:
curl --request GET \
  --url 'https://api.sorsa.io/v3/followers?username=elonmusk&cursor=abc123' \
  --header 'ApiKey: YOUR_API_KEY'
POST endpoints accept the cursor in the JSON body:
curl --request POST \
  --url 'https://api.sorsa.io/v3/search-tweets' \
  --header 'ApiKey: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"query": "bitcoin", "next_cursor": "abc123"}'
Python example: paginating through all followers
import time
import requests

API_KEY = "YOUR_API_KEY"
all_users = []
cursor = None

while True:
    params = {"username": "elonmusk"}
    if cursor:
        params["cursor"] = cursor

    response = requests.get(
        "https://api.sorsa.io/v3/followers",
        params=params,
        headers={"ApiKey": API_KEY}
    )
    data = response.json()

    all_users.extend(data["users"])
    cursor = data.get("next_cursor")

    if not cursor:
        break

    time.sleep(0.05)  # respect rate limit

print(f"Fetched {len(all_users)} followers")
For a deeper look at pagination strategies and performance tips, see Pagination.

Next steps

  • Pagination - Advanced pagination patterns and best practices
  • Error Codes - How error responses are structured
  • API Reference - Full endpoint schemas with request and response examples