X API
Read public X posts by search query or user timeline, explore trending topics, retrieve post details and replies, and extract linked articles. Supports paginated results and incremental user-timeline checks. Read-only; does not publish posts or change accounts.
Endpoint health
Loading verification…
Connect your agent
Connect through MCP so your agent can find this API, read its docs, and call its endpoints.
Add the server from your terminal.
claude mcp add --transport http agent-data https://agent-data.motie.dev/mcpIn Claude Code, run /mcp, select agent-data, then Authenticate. Sign in to your agent-data account in the browser.
Then ask your agent to use the X API for your task.
Call it over HTTP
Get an API keySign up free, generate an API key, and set it as AGENT_DATA_API_KEY in your environment. Your first 100 calls each month are free.
curl --request GET --get 'https://api.agent-data.dev/x-com/v1/feed' \
--header "Authorization: Bearer $AGENT_DATA_API_KEY"Endpoints
Inputs and response fields for every endpoint in this API.
GETFeed/v1/feed
Feed
Input
qOptionalQuery · string | nullX search query. Supply exactly one of q, user or trend.
Example: from:OpenAI
userOptionalQuery · string | nullOne X handle, with or without @. Supply exactly one of q, user or trend.
Example: OpenAI
trendOptionalQuery · "trending" | "news" | "sport" | "entertainment" | nullExplore category. Trend entries can be topics rather than posts; only numeric item_id values support post detail.
Example: news
limitOptionalQuery · integer, min: 1, max: 100, default: 20Maximum returned items. Default 20; maximum 100. Larger requests may require more upstream pages.
Example: 3
cursorOptionalQuery · string | nullOpaque next_cursor from this same query. Keep q/user/trend unchanged. Upstream cursors may expire; restart the query if rejected.
since_tokenOptionalQuery · string | nullCheckpoint from meta.next_since_token. Supported only for user timelines, mutually exclusive with cursor. Check meta.checkpoint_status for incomplete catch-up.
Example: Copy meta.next_since_token from a user feed
Response
dataobject[]data[].idstringdata[].url?string | nulldata[].title?string | nulldata[].author?string | nulldata[].sourcestringdata[].channelstringdata[].item_idstringdata[].permalinkstringdata[].created_atstring (date-time)data[].engagementobjectdata[].engagement.score?integer | nulldata[].engagement.view_count?integer | nulldata[].engagement.quote_count?integer, default: 0data[].engagement.upvote_count?integer | nulldata[].engagement.comment_count?integer, default: 0data[].engagement.retweet_count?integer, default: 0data[].engagement.bookmark_count?integer, default: 0data[].engagement.poll_option_count?integer, default: 0data[].body_preview?string | nullmetaobjectmeta.error?string | nullmeta.sourcestringmeta.last_id?string | nullmeta.has_more?boolean, default: falsemeta.returnedintegermeta.generated_atstring (date-time)meta.next_page_token?string | nullmeta.pagination_mode?string | nullmeta.checkpoint_error?string | nullmeta.next_since_token?string | nullmeta.pagination_notes?object | nullmeta.result_direction?"desc" | "asc"meta.checkpoint_status?"ok" | "expired" | "partial"meta.oldest_item_age_seconds?integer | nullpaginationobjectpagination.has_morebooleanpagination.next_cursorstring | nullrequest_idstringFields marked ? are optional.
For the next page, pass next_cursor from the response as cursor. Leave it empty on the first call.
GETPost/v1/posts/{post_id}
Post
Input
post_idRequiredPath · stringNumeric X post ID (item_id), or the x_-prefixed id returned by feed. Trend topic IDs are not post IDs.
Example: 2102460995180663204
Response
dataobjectdata.idstringdata.url?string | nulldata.title?string | nulldata.author?string | nulldata.sourcestringdata.threadobject[]data.thread[].idstringdata.thread[].body?string | nulldata.thread[].author?string | nulldata.thread[].sourcestringdata.thread[].item_idstringdata.thread[].upvotes?integer | nulldata.thread[].comments?unknown[]data.thread[].permalinkstringdata.thread[].created_atstring (date-time)data.thread[].number_of_comments?integer, default: 0data.item_idstringdata.full_body?string | nulldata.permalinkstringdata.created_atstring (date-time)data.engagementobjectdata.engagement.score?integer | nulldata.engagement.view_count?integer | nulldata.engagement.quote_count?integer, default: 0data.engagement.upvote_count?integer | nulldata.engagement.comment_count?integer, default: 0data.engagement.retweet_count?integer, default: 0data.engagement.bookmark_count?integer, default: 0data.engagement.poll_option_count?integer, default: 0data.availability?objectdata.availability.reason?string | nulldata.availability.status?"available" | "unavailable"data.availability.final_permalink?string | nulldata.author_context?objectdata.author_context.idstringdata.author_context.about?string | nulldata.author_context.karma?integer | nulldata.author_context.verified?boolean | nulldata.author_context.created_at?string (date-time) | nulldata.author_context.tweet_count?integer | nulldata.author_context.display_name?string | nulldata.author_context.followers_count?integer | nulldata.author_context.following_count?integer | nulldata.author_context.submitted_count?integer, default: 0data.comment_pagination?objectdata.comment_pagination.has_more?boolean, default: falsedata.comment_pagination.returnedintegerdata.comment_pagination.next_page_token?string | nulldata.linked_content_preview?objectdata.linked_content_preview.urlstringdata.linked_content_preview.title?string | nulldata.linked_content_preview.domainstringdata.linked_content_preview.warnings?string[]data.linked_content_preview.word_count?integer, default: 0data.linked_content_preview.chunk_count?integer, default: 0data.linked_content_preview.content_kind"article" | "repo_page" | "video_page" | "landing_page" | "research_page" | "unknown"data.linked_content_preview.fetch_status"ok" | "http_error" | "timeout" | "non_html" | "extract_failed"data.linked_content_preview.excerpt_markdown?string | nulldata.linked_content_preview.linked_content_resourcestringrequest_idstringFields marked ? are optional.
GETLinked content/v1/posts/{post_id}/linked-content
Linked Content
Input
post_idRequiredPath · stringNumeric X post ID (item_id), or the x_-prefixed id returned by feed. Trend topic IDs are not post IDs.
Example: 2102460995180663204
cursorOptionalQuery · string | nullOpaque next_cursor for the same post linked-content resource. Content is fetched again, so changing pages can change chunk boundaries.
limitOptionalQuery · integer, min: 1, max: 3, default: 1Maximum article chunks returned, from 1 to 3.
Example: 1
Response
dataobjectdata.sourcestringdata.item_idstringdata.story_idstringdata.linked_contentobjectdata.linked_content.urlstringdata.linked_content.title?string | nulldata.linked_content.chunks?object[]data.linked_content.chunks[].chunk_idstringdata.linked_content.chunks[].markdownstringdata.linked_content.chunks[].sequenceintegerdata.linked_content.chunks[].end_word_indexintegerdata.linked_content.chunks[].start_word_indexintegerdata.linked_content.domainstringdata.linked_content.warnings?string[]data.linked_content.final_url?string | nulldata.linked_content.paginationobjectdata.linked_content.pagination.chunk_count?integer, default: 0data.linked_content.pagination.max_page_sizeintegerdata.linked_content.pagination.next_page_token?string | nulldata.linked_content.word_count?integer, default: 0data.linked_content.content_kind"article" | "repo_page" | "video_page" | "landing_page" | "research_page" | "unknown"data.linked_content.content_type?string | nulldata.linked_content.fetch_status"ok" | "http_error" | "timeout" | "non_html" | "extract_failed"paginationobjectpagination.has_morebooleanpagination.next_cursorstring | nullrequest_idstringFields marked ? are optional.
For the next page, pass next_cursor from the response as cursor. Leave it empty on the first call.
Don’t see the endpoint you need?
Ask agent-data to add an endpoint or return more fields. Extensions are free and keep existing endpoints working.
An account is required to submit an extension. Prepare your request, then sign in to build.