Get up to 100 public X posts by id
GET /v1/x/posts
Looks up many posts in one request, for hydrating ids you already hold (from a webhook, a dataset, or another response). Posts come back in the order requested. An id that cannot be returned is listed in meta.notFound instead of failing the request, and is not billed. Billed per post returned.
Price: 1 credit per call, plus 1 credit per X post returned. Failed and refused calls cost nothing.
Rate limit: Counts as 2 requests against your per-minute rate limit.
MCP tool: get_x_posts, on every MCP connection.
Requires an API key, sent as Authorization: Bearer <key>.
Request
curl --request GET \
--url https://api.weirapp.io/v1/x/posts?ids=IDS \
--header "Authorization: Bearer $WEIR_API_KEY"Query parameters
| Field | Type | Required | Notes |
|---|---|---|---|
ids |
string | yes | Comma-separated numeric post ids, 1 to 100, no spaces. Duplicates are ignored. · matches ^\d{1,19}(,\d{1,19}){0,99}$ |
Response
The posts found, in request order.
200
| Field | Type | Required | Notes |
|---|---|---|---|
data |
array of object | yes | |
data[].id |
string | yes | Numeric post id, as a string. It exceeds 2^53. |
data[].text |
string | yes | Full post text, untruncated. |
data[].url |
string | yes | |
data[].lang |
string or null | yes | BCP-47 language tag detected by X. |
data[].createdAt |
string (date-time) | yes | |
data[].conversationId |
string or null | yes | The thread this post belongs to. |
data[].inReplyToId |
string or null | yes | |
data[].author |
object | yes | |
data[].author.id |
string | yes | |
data[].author.username |
string | yes | |
data[].author.name |
string | yes | |
data[].author.verified |
boolean | yes | |
data[].author.followersCount |
integer | yes | min 0 |
data[].author.profileImageUrl |
string or null | yes | |
data[].likeCount |
integer or null | yes | min 0 |
data[].retweetCount |
integer or null | yes | min 0 |
data[].replyCount |
integer or null | yes | min 0 |
data[].viewCount |
integer or null | yes | min 0 |
data[].quoteCount |
integer or null | yes | min 0 |
data[].bookmarkCount |
integer or null | yes | min 0 |
data[].media |
array of object | yes | Attached photos, videos, and GIFs, in display order. |
data[].media[].id |
string | yes | |
data[].media[].type |
string | yes | X's own media type names. · photo, video, animated_gif |
data[].media[].url |
string or null | yes | The image for a photo; the highest-bitrate MP4 for a video or GIF. Null when X offers only a stream. |
data[].media[].previewImageUrl |
string or null | yes | Poster frame for a video. Null for photos and GIFs. |
data[].entities |
object | yes | |
data[].entities.hashtags |
array of string | yes | Hashtags, without the #. |
data[].entities.mentions |
array of string | yes | Mentioned usernames, without the @. |
data[].entities.urls |
array of string | yes | Expanded link targets, not t.co short links. |
data[].quotedPost |
object or null | yes | The post this one quotes, when it is a quote post. |
data[].quotedPost.id |
string | yes | Numeric post id, as a string. It exceeds 2^53. |
data[].quotedPost.text |
string | yes | Full post text, untruncated. |
data[].quotedPost.url |
string | yes | |
data[].quotedPost.lang |
string or null | yes | BCP-47 language tag detected by X. |
data[].quotedPost.createdAt |
string (date-time) | yes | |
data[].quotedPost.conversationId |
string or null | yes | The thread this post belongs to. |
data[].quotedPost.inReplyToId |
string or null | yes | |
data[].quotedPost.author |
object | yes | |
data[].quotedPost.author.id |
string | yes | |
data[].quotedPost.author.username |
string | yes | |
data[].quotedPost.author.name |
string | yes | |
data[].quotedPost.author.verified |
boolean | yes | |
data[].quotedPost.author.followersCount |
integer | yes | min 0 |
data[].quotedPost.author.profileImageUrl |
string or null | yes | |
data[].quotedPost.likeCount |
integer or null | yes | min 0 |
data[].quotedPost.retweetCount |
integer or null | yes | min 0 |
data[].quotedPost.replyCount |
integer or null | yes | min 0 |
data[].quotedPost.viewCount |
integer or null | yes | min 0 |
data[].quotedPost.quoteCount |
integer or null | yes | min 0 |
data[].quotedPost.bookmarkCount |
integer or null | yes | min 0 |
data[].quotedPost.media |
array of object | yes | Attached photos, videos, and GIFs, in display order. |
data[].quotedPost.media[].id |
string | yes | |
data[].quotedPost.media[].type |
string | yes | X's own media type names. · photo, video, animated_gif |
data[].quotedPost.media[].url |
string or null | yes | The image for a photo; the highest-bitrate MP4 for a video or GIF. Null when X offers only a stream. |
data[].quotedPost.media[].previewImageUrl |
string or null | yes | Poster frame for a video. Null for photos and GIFs. |
data[].quotedPost.entities |
object | yes | |
data[].quotedPost.entities.hashtags |
array of string | yes | Hashtags, without the #. |
data[].quotedPost.entities.mentions |
array of string | yes | Mentioned usernames, without the @. |
data[].quotedPost.entities.urls |
array of string | yes | Expanded link targets, not t.co short links. |
data[].retweetedPost |
object or null | yes | Set when this post is a repost. Read the original's text and counts here: X truncates a repost's own text to RT @user: …. |
data[].retweetedPost.id |
string | yes | Numeric post id, as a string. It exceeds 2^53. |
data[].retweetedPost.text |
string | yes | Full post text, untruncated. |
data[].retweetedPost.url |
string | yes | |
data[].retweetedPost.lang |
string or null | yes | BCP-47 language tag detected by X. |
data[].retweetedPost.createdAt |
string (date-time) | yes | |
data[].retweetedPost.conversationId |
string or null | yes | The thread this post belongs to. |
data[].retweetedPost.inReplyToId |
string or null | yes | |
data[].retweetedPost.author |
object | yes | |
data[].retweetedPost.author.id |
string | yes | |
data[].retweetedPost.author.username |
string | yes | |
data[].retweetedPost.author.name |
string | yes | |
data[].retweetedPost.author.verified |
boolean | yes | |
data[].retweetedPost.author.followersCount |
integer | yes | min 0 |
data[].retweetedPost.author.profileImageUrl |
string or null | yes | |
data[].retweetedPost.likeCount |
integer or null | yes | min 0 |
data[].retweetedPost.retweetCount |
integer or null | yes | min 0 |
data[].retweetedPost.replyCount |
integer or null | yes | min 0 |
data[].retweetedPost.viewCount |
integer or null | yes | min 0 |
data[].retweetedPost.quoteCount |
integer or null | yes | min 0 |
data[].retweetedPost.bookmarkCount |
integer or null | yes | min 0 |
data[].retweetedPost.media |
array of object | yes | Attached photos, videos, and GIFs, in display order. |
data[].retweetedPost.media[].id |
string | yes | |
data[].retweetedPost.media[].type |
string | yes | X's own media type names. · photo, video, animated_gif |
data[].retweetedPost.media[].url |
string or null | yes | The image for a photo; the highest-bitrate MP4 for a video or GIF. Null when X offers only a stream. |
data[].retweetedPost.media[].previewImageUrl |
string or null | yes | Poster frame for a video. Null for photos and GIFs. |
data[].retweetedPost.entities |
object | yes | |
data[].retweetedPost.entities.hashtags |
array of string | yes | Hashtags, without the #. |
data[].retweetedPost.entities.mentions |
array of string | yes | Mentioned usernames, without the @. |
data[].retweetedPost.entities.urls |
array of string | yes | Expanded link targets, not t.co short links. |
meta |
object | yes | |
meta.requestId |
string | yes | |
meta.notFound |
array of string | yes | Requested ids that came back empty: deleted, suspended, protected, withheld, or never existed. They cost nothing. |
Errors
| Status | Meaning | What to do |
|---|---|---|
400 |
The request failed validation. | The request was malformed. The details object names the field. |
401 |
The API key is missing, malformed, expired, or revoked. | The key is missing, malformed, revoked, or expired. |
402 |
The account is out of credit. Not retryable: this cannot clear until the billing period resets or the plan changes. | Out of credits. Never retry. Only a person can clear it, by adding credits at https://weirapp.io/dashboard/billing. Retrying never will. |
403 |
The API key does not carry the scope this route requires. | The key is valid but lacks the scope this operation needs. |
404 |
The requested resource does not exist. | No such resource, or it is not public. |
429 |
The per-minute rate limit is exhausted. Retryable: wait for Retry-After and try again. | Rate limited. Retryable: wait for Retry-After, then try again. |
500 |
An unexpected error occurred. | Something failed on our side. Retryable with backoff. |
503 |
The source is temporarily unavailable. The request is safe to retry. | A source was unreachable. Retryable with backoff. |