openapi: 3.1.0 info: title: Xquik API version: '1.0' description: >- Xquik is an independent third-party service. Not affiliated with X Corp. "Twitter" and "X" are trademarks of X Corp. Read and automate X. Paid reads accept credits. Some lookups accept MPP. Writes require an API key or OAuth 2.1. Shared-account reads return public posts only. ## Rate limits Every authenticated response carries `RateLimit-Policy`, your limit for that kind of request, and `RateLimit`, your requests left & seconds until the window resets. A refused request gets 429 with `Retry-After`. ## Credits charged An answer to a read carries `X-Xquik-Credits-Charged`, the credits that request charged. It is 0 for a page a filter empties & for a page sent again. A write names its charge in its body's `billing`. ## Deprecation v1 stays compatible. A breaking removal gets at least 90 days of notice. A request with a deprecated query parameter or search filter gets an RFC 9745 `Deprecation` header. The answer's `Link` header points to the [deprecation policy](https://xquik.com/deprecation-policy.md). Once a removal date is set, an RFC 8594 `Sunset` header gives that date. Each operation that sends these headers declares them on its success answer. The [versioning guide](https://docs.xquik.com/guides/versioning) lists today's deprecations. ## Client libraries [SDK, CLI, Terraform](https://docs.xquik.com/sdks) and [TweetClaw](https://docs.xquik.com/guides/tweetclaw). contact: name: Xquik url: https://xquik.com email: support@xquik.com license: name: Proprietary url: https://xquik.com/en/terms servers: - url: https://xquik.com/api/v1 x-service-info: categories: - data docs: homepage: https://xquik.com apiReference: https://docs.xquik.com llms: https://docs.xquik.com/llms.txt x-discovery: ownershipProofs: - 'dns:xquik.com' security: &api-auth [{ apiKey: [] }, { oauthBearer: [] }] tags: - name: API Keys description: API key management (session auth only) - name: Account description: Account info and settings - name: Agent Discovery description: Public agent discovery and documentation search - name: Analysis description: AI analysis of posts, at 2 credits per analyzed post - name: Articles description: Long-form X Article extraction - name: Broadcasts description: X live video details, watch counts, and broadcaster - name: Communities description: Find X Communities & read their info, members, posts & media - name: Community Notes description: Community Notes contributors, their notes, ratings & deleted notes - name: Composition description: AI tweet composition, drafts, writing styles, and radar - name: Draws description: Giveaway draws from tweet replies - name: Events description: Activity events from monitored accounts - name: Extractions description: Saved or bulk data extraction (23 tool types) - name: Guest Wallets description: Accountless prepaid access for paid read endpoints - name: Jobs description: Public X job listings, search and details - name: Lists description: X List search, details, followers, members, and tweets - name: Media description: Media upload and download - name: Monitors description: X account monitoring with 1-second checks - name: Spaces description: X Space details, host, and speakers - name: Subscribe description: Subscription, billing, and credits - name: Support description: Support ticket management - name: Trends description: Trending topics and hashtags by region - name: Tweets description: Look up, search, and analyze individual tweets - name: Users description: Look up, search, and explore user profiles and relationships - name: Webhooks description: Webhook endpoint management and delivery - name: X Accounts description: Connected X accounts. Sign-in & removal need a dashboard session. - name: X Write description: X write actions (tweets, likes, follows, DMs) paths: /ask: servers: - url: https://xquik.com post: operationId: searchXquikDocumentation x-mcp-exclusion-reason: &agent-discovery Public agent discovery remains direct. summary: Search Xquik documentation with NLWeb description: >- Search public Xquik docs with NLWeb 0.55. This read-only route accepts flat and structured requests. Never send secrets or private data. tags: [Agent Discovery] security: [{}] requestBody: description: Flat or structured NLWeb request. required: true content: application/json: schema: $ref: '#/components/schemas/NlwebAskRequest' examples: flat: summary: 'A flat request' value: query: 'How does MCP OAuth work?' site: 'docs.xquik.com' streaming: false response_format: 'conversational_search' mode: 'list' context: previous_query: 'How does OAuth work?' meta: api_version: '0.55' structured: summary: 'A structured request' value: query: text: 'How does MCP OAuth work?' site: 'docs.xquik.com' prefer: mode: 'list' response_format: 'chatgpt_app' streaming: false meta: api_version: '0.55' application/x-www-form-urlencoded: schema: $ref: '#/components/schemas/NlwebAskRequest' responses: '200': description: Documentation results. content: application/json: schema: $ref: '#/components/schemas/NlwebAnswer' example: _meta: response_format: conversational_search response_type: answer version: '0.55' results: [] text/event-stream: schema: type: string '400': description: Invalid or unsupported NLWeb request. content: application/json: schema: $ref: '#/components/schemas/NlwebFailure' example: _meta: { response_type: failure, version: '0.55' } error: code: INVALID_QUERY message: 'Request is invalid. Send a valid NLWeb query.' '413': description: Request body exceeds 8 KiB. content: application/json: schema: $ref: '#/components/schemas/NlwebFailure' example: _meta: { response_type: failure, version: '0.55' } error: code: TOKEN_LIMIT message: 'Request is too large. Send less context.' '502': description: Documentation search is unavailable. content: application/json: schema: $ref: '#/components/schemas/NlwebFailure' example: _meta: { response_type: failure, version: '0.55' } error: code: INTERNAL_ERROR message: 'Search is unavailable. Retry later.' get: operationId: searchXquikDocumentationWithQuery x-mcp-exclusion-reason: *agent-discovery summary: Search Xquik documentation with query parameters description: Send a flat NLWeb 0.55 request through query parameters. tags: [Agent Discovery] security: [{}] parameters: - name: query in: query required: true description: Natural-language docs query. schema: { type: string, minLength: 1, maxLength: 500 } - name: site in: query description: Optional docs host. schema: { type: string, enum: [docs.xquik.com, xquik.com] } - name: mode in: query description: List result mode. schema: { type: string, const: list } - name: response_format in: query description: NLWeb response shape. schema: type: string enum: [chatgpt_app, conversational_search] default: conversational_search - name: streaming in: query description: Return SSE when true. schema: { type: boolean, default: false } responses: '200': { $ref: '#/paths/~1ask/post/responses/200' } '400': { $ref: '#/paths/~1ask/post/responses/400' } '413': { $ref: '#/paths/~1ask/post/responses/413' } '502': { $ref: '#/paths/~1ask/post/responses/502' } # ── Account ────────────────────────────────────────────── /account: get: operationId: getAccount description: Returns plan, credit, monitoring, and account settings for the authenticated user. summary: Get account info tags: [Account] security: *api-auth responses: '200': description: Account info headers: &deprecated-read-headers Deprecation: { $ref: '#/components/headers/Deprecation' } Link: { $ref: '#/components/headers/DeprecationLink' } content: application/json: schema: type: object required: [ plan, subscription, monitorsUsed, monitorsAllowed, monitorBilling, ] properties: plan: type: string enum: [active, inactive] example: active subscription: type: object description: Subscription state without billing provider identifiers. required: [status] properties: status: type: string enum: [none, active, past_due, canceling, incomplete] example: active tier: type: string enum: [starter, pro, business] example: pro currentPeriodStart: type: string format: date-time example: '2026-09-01T00:00:00.000Z' currentPeriodEnd: type: string format: date-time description: Renewal date, or the end date when canceling. example: '2026-10-01T00:00:00.000Z' monitorsUsed: type: integer minimum: 0 example: 3 monitorsAllowed: type: integer minimum: 0 deprecated: true x-stainless-deprecation-message: Monitor slots are unlimited. Use monitorBilling.unlimitedSlots instead. description: Deprecated. Monitor slots are unlimited, so this is always Number.MAX_SAFE_INTEGER. example: 9007199254740991 monitorBilling: type: object required: [ activeDailyEstimate, activeHourlyBurn, creditsPerActiveMonitorDay, creditsPerActiveMonitorHour, eventsIncluded, instantCheckIntervalSeconds, unlimitedSlots, ] properties: activeDailyEstimate: type: string minLength: 1 maxLength: 13 pattern: &nonnegative-credit-string '^(0|[1-9][0-9]*)$' not: &credit-whitespace type: string pattern: '\s' description: Daily credits for active monitors. example: '2160' activeHourlyBurn: type: string minLength: 1 maxLength: 11 pattern: *nonnegative-credit-string not: *credit-whitespace description: Credits charged each hour for active monitors. example: '90' creditsPerActiveMonitorDay: type: string enum: ['720'] description: Daily credits charged for 1 active monitor. example: '720' creditsPerActiveMonitorHour: type: string enum: ['30'] description: Hourly credits charged for 1 active monitor. It is a monitor's only charge. example: '30' eventsIncluded: type: boolean description: Monitor billing includes webhook and event deliveries. example: true instantCheckIntervalSeconds: type: integer minimum: 1 description: Active monitors check every 1 second. example: 1 unlimitedSlots: type: boolean description: Monitor slot count is unlimited. example: true creditInfo: type: object required: [ balance, lifetimePurchased, lifetimeUsed, autoTopupEnabled, autoTopupStopped, autoTopupAmountDollars, autoTopupThreshold, ] properties: balance: type: string minLength: 1 maxLength: 19 pattern: *nonnegative-credit-string not: *credit-whitespace description: Credit balance as a bigint string, which keeps precision above Number.MAX_SAFE_INTEGER. example: '50000' lifetimePurchased: type: string minLength: 1 maxLength: 20 pattern: &signed-credit-string '^(0|-?[1-9][0-9]*)$' not: *credit-whitespace description: Total purchased credits as a bigint string. example: '140000' lifetimeUsed: type: string minLength: 1 maxLength: 20 pattern: *signed-credit-string not: *credit-whitespace description: Total consumed credits as a bigint string. example: '90000' autoTopupEnabled: &boolean-example-false type: boolean example: false autoTopupStopped: type: boolean description: True when 3 declined charges in a row on 1 card stopped automatic top-up. The setting stays enabled. A paid top-up, a paid plan renewal, or the next automatic top-up on a new card clears it. example: false autoTopupAmountDollars: type: number description: Dollar amount charged when automatic top-up runs. example: 10 autoTopupThreshold: type: string enum: ['10000', '50000', '100000', '250000'] description: Bigint string threshold that triggers automatic top-up when enabled. example: '50000' xUsername: type: string description: Linked X username, omitted when no X account is connected. example: elonmusk example: plan: active subscription: status: active tier: pro currentPeriodStart: '2026-09-01T00:00:00.000Z' currentPeriodEnd: '2026-10-01T00:00:00.000Z' monitorsUsed: 3 monitorsAllowed: 9007199254740991 monitorBilling: activeDailyEstimate: '2160' activeHourlyBurn: '90' creditsPerActiveMonitorDay: '720' creditsPerActiveMonitorHour: '30' eventsIncluded: true instantCheckIntervalSeconds: 1 unlimitedSlots: true creditInfo: balance: '50000' lifetimePurchased: '140000' lifetimeUsed: '90000' autoTopupEnabled: false autoTopupStopped: false autoTopupAmountDollars: 10 autoTopupThreshold: '50000' xUsername: elonmusk '401': &unauthenticated-response $ref: '#/components/responses/Unauthenticated' '429': &rate-limit-exceeded-response $ref: '#/components/responses/RateLimitExceeded' patch: operationId: updateAccount description: Changes the locale used for account responses and notifications. summary: Update account locale tags: [Account] security: *api-auth requestBody: required: true description: Locale preference for the account. content: application/json: schema: type: object required: [locale] properties: locale: type: string enum: [en, tr, es] example: en example: locale: en responses: '200': description: Locale updated content: application/json: schema: allOf: - type: object required: [success] properties: success: type: boolean const: true example: true - $ref: '#/components/schemas/IgnoredFieldsNotice' example: success: true '400': &invalid-input-response $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '429': *rate-limit-exceeded-response /account/x-identity: put: operationId: setXIdentity description: Links an X username to the authenticated Xquik account. summary: Set linked X username tags: [Account] security: *api-auth requestBody: required: true description: X username to link to this account. content: application/json: schema: type: object required: [username] properties: username: type: string minLength: 1 maxLength: 15 pattern: '^[A-Za-z0-9_]{1,15}$' description: X username without @ example: elonmusk example: username: elonmusk responses: '200': description: X identity linked content: application/json: schema: type: object required: [success, xUsername] properties: success: &boolean-true type: boolean const: true xUsername: &handle-example-schema type: string example: elonmusk example: success: true xUsername: elonmusk '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response # ── API Keys ───────────────────────────────────────────── /api-keys: get: operationId: listApiKeys x-mcp-exclusion-reason: &browser-auth Credential management requires browser auth. description: Returns API key metadata without exposing secret key values. summary: List API keys tags: [API Keys] security: [{ cookieSession: [] }] parameters: &list-limit-after-parameters - $ref: '#/components/parameters/ListLimit' - $ref: '#/components/parameters/After' responses: '200': description: API key list content: application/json: schema: type: object required: [keys, hasMore] properties: keys: type: array items: $ref: '#/components/schemas/ApiKey' example: [] hasMore: *boolean-example-false nextCursor: &short-id-example-schema type: string example: 'abc123' example: keys: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '429': *rate-limit-exceeded-response post: operationId: createApiKey x-mcp-exclusion-reason: *browser-auth description: Creates a revocable API key and returns its secret once. summary: Create API key tags: [API Keys] security: [{ cookieSession: [] }] requestBody: required: true description: Optional display name for the new API key. content: application/json: schema: type: object properties: name: type: string maxLength: 100 description: Up to 100 characters. An empty or missing name saves the key as Default. example: My API Key example: name: My API Key responses: '201': description: API key created content: application/json: schema: type: object required: [id, fullKey, name, prefix, createdAt] properties: id: &resource-id-example-schema type: string example: '42' fullKey: type: string example: xq_live_example_key name: type: string example: My API Key prefix: type: string example: xq_live_exam createdAt: &created-at-schema type: string format: date-time example: '2025-01-15T12:00:00Z' example: id: '42' fullKey: xq_live_example_key name: My API Key prefix: xq_live_exam createdAt: '2025-01-15T12:00:00Z' '401': *unauthenticated-response '403': description: API key limit reached, or an API key or OAuth token sent instead of a dashboard session content: application/json: schema: anyOf: - type: object title: ApiKeyLimitReached required: [error, limit, message] properties: error: type: string const: api_key_limit_reached example: api_key_limit_reached limit: type: integer minimum: 1 example: 100 message: type: string example: API key limit reached. Delete an existing key first. - $ref: '#/components/schemas/Error' examples: limitReached: summary: API key limit reached value: error: api_key_limit_reached limit: 100 message: API key limit reached. Delete an existing key first. sessionRequired: summary: API key or OAuth token sent value: &session-required-example error: session_required message: API keys & OAuth tokens cannot use this route. Sign in at dashboard.xquik.com/account instead. '429': *rate-limit-exceeded-response /api-keys/{id}: delete: operationId: revokeApiKey x-mcp-exclusion-reason: *browser-auth description: Permanently revokes the selected API key. summary: Revoke API key tags: [API Keys] security: [{ cookieSession: [] }] parameters: &resource-id-parameters - $ref: '#/components/parameters/ResourceId' responses: '200': $ref: '#/components/responses/Success' '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '404': ¬-found-response $ref: '#/components/responses/NotFound' '429': *rate-limit-exceeded-response # ── Subscribe ──────────────────────────────────────────── /subscribe: post: operationId: subscribe x-mcp-exclusion-reason: &browser-checkout Browser checkout requires user interaction. summary: Create subscription checkout description: > Create a subscription checkout URL or a billing page link only after the user confirms. The request never completes payment by itself. An account with a plan gets the dashboard billing page, where the user signs in to manage billing. tags: [Subscribe] security: *api-auth requestBody: required: false description: Optional subscription tier to pre-select at checkout. content: application/json: schema: type: object properties: tier: type: string enum: [starter, pro, business] description: Subscription tier to pre-select. example: pro example: tier: pro responses: '200': description: Billing URL content: application/json: schema: type: object required: [url, status, message] properties: url: type: string format: uri description: Checkout URL, or the dashboard billing page for an account with a plan. example: 'https://xquik.com/billing/session' status: type: string enum: [checkout_created, already_subscribed, payment_issue] example: checkout_created message: type: string example: Billing session created example: url: 'https://xquik.com/billing/session' status: checkout_created message: Billing session created '401': *unauthenticated-response '429': *rate-limit-exceeded-response # ── Composition ────────────────────────────────────────── /compose: post: operationId: compose x-mcp-annotations: { readOnlyHint: true } summary: Build, refine, or check a post draft description: Uses xai-org/x-algorithm facts to compose and refine text. The score step checks text. It never predicts reach or engagement. tags: [Composition] security: *api-auth requestBody: required: true description: Send exactly 1 workflow step and its required fields. content: application/json: schema: oneOf: - $ref: '#/components/schemas/ComposePrepareRequest' - $ref: '#/components/schemas/ComposeRefineRequest' - $ref: '#/components/schemas/ComposeScoreRequest' examples: compose: summary: 'Start a draft' value: step: 'compose' topic: 'PostgreSQL query planning' goal: 'engagement' styleUsername: 'example_user' refine: summary: 'Refine the draft' value: step: 'refine' topic: 'PostgreSQL query planning' goal: 'authority' tone: 'professional' mediaType: 'photo' callToAction: 'Reply with your slowest query.' additionalContext: 'Audience: backend engineers. Keep it under 280 characters.' score: summary: 'Check a finished draft' value: step: 'score' draft: 'EXPLAIN ANALYZE shows where PostgreSQL spends its time. Run it on your slowest query today.' hasLink: false hasMedia: false responses: '200': description: Result for the requested workflow step content: application/json: schema: oneOf: - $ref: '#/components/schemas/ComposePrepareResult' - $ref: '#/components/schemas/ComposeRefineResult' - $ref: '#/components/schemas/ComposeScoreResult' example: checklist: - factor: Draft contains text passed: true nextStep: > Draft accepted. Publish through POST /api/v1/x/tweets or use intentUrl. passed: true passedCount: 1 topSuggestion: >- No deterministic ranking score exists. Ranking uses per-viewer predictions. totalChecks: 1 intentUrl: >- https://x.com/intent/tweet?text=PostgreSQL%2018%20reduced%20query%20latency '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response /drafts: get: operationId: listDrafts description: Lists private Xquik drafts. It cannot access native X drafts. summary: List saved drafts tags: [Composition] security: *api-auth parameters: - $ref: '#/components/parameters/Limit' - name: afterCursor in: query schema: type: string maxLength: 128 description: Cursor for pagination. The after alias also works. responses: '200': description: Draft list content: application/json: schema: type: object required: [drafts, hasMore] properties: drafts: type: array items: $ref: '#/components/schemas/Draft' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: drafts: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createDraft description: Stores a private Xquik draft. It never publishes or creates native X drafts. summary: Save a tweet draft tags: [Composition] security: *api-auth requestBody: required: true description: Draft text with optional topic and optimization goal. content: application/json: schema: type: object required: [text] properties: text: type: string minLength: 1 maxLength: 25000 description: Draft text, up to 25,000 characters. An emoji counts as 2. example: 'AI is the future of productivity' topic: type: string maxLength: 25000 description: Optional topic, up to 25,000 characters. Xquik keeps the first 500. example: 'AI trends' goal: type: string enum: [engagement, followers, authority, conversation] example: engagement example: text: 'AI is the future of productivity' topic: 'AI trends' goal: engagement responses: '201': description: Draft created content: application/json: schema: allOf: - $ref: '#/components/schemas/DraftDetail' - $ref: '#/components/schemas/IgnoredFieldsNotice' example: id: '42' text: 'AI is the future of productivity' topic: 'AI trends' goal: engagement createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-01-16T09:30:00Z' '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response /drafts/{id}: get: operationId: getDraft description: Returns 1 private Xquik draft. It cannot access native X drafts. summary: Get draft by ID tags: [Composition] security: *api-auth parameters: *resource-id-parameters responses: '200': description: Draft details content: application/json: schema: $ref: '#/components/schemas/DraftDetail' example: id: '42' text: 'AI is the future of productivity' topic: 'AI trends' goal: engagement createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-01-16T09:30:00Z' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response delete: operationId: deleteDraft description: Deletes 1 Xquik draft, not native X drafts or published posts. summary: Delete a draft tags: [Composition] security: *api-auth parameters: *resource-id-parameters responses: '204': $ref: '#/components/responses/NoContent' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /styles: get: operationId: listStyles description: Returns cached writing style profiles for the account. summary: List cached style profiles tags: [Composition] security: *api-auth parameters: *list-limit-after-parameters responses: '200': description: Style profile list content: application/json: schema: type: object required: [styles, hasMore] properties: styles: type: array items: $ref: '#/components/schemas/StyleProfileSummary' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: styles: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: analyzeStyle description: Builds a writing style profile from recent public posts. summary: Analyze writing style from recent tweets tags: [Composition] security: *api-auth requestBody: required: true description: X username whose recent tweets define the style. content: application/json: schema: type: object required: [username] properties: username: type: string maxLength: 64 description: X username to analyze example: elonmusk example: username: elonmusk responses: '200': description: Fresh cached style profile returned content: &style-profile-content-with-example application/json: schema: $ref: '#/components/schemas/StyleProfile' '201': description: Style profile created or refreshed content: *style-profile-content-with-example '400': *invalid-input-response '401': *unauthenticated-response '402': &payment-required-response $ref: '#/components/responses/PaymentRequired' '429': *rate-limit-exceeded-response /styles/compare: get: operationId: compareStyles description: Compares language and engagement signals across 2 style profiles. summary: Compare 2 style profiles tags: [Composition] security: *api-auth parameters: - name: username1 in: query required: true schema: type: string maxLength: 64 description: First username to compare - name: username2 in: query required: true schema: type: string maxLength: 64 description: Second username to compare responses: '200': description: Style comparison content: application/json: schema: type: object required: [style1, style2] properties: style1: $ref: '#/components/schemas/StyleProfile' style2: $ref: '#/components/schemas/StyleProfile' example: style1: &style-profile-example xUsername: 'elonmusk' tweetCount: 50 isOwnAccount: true fetchedAt: '2025-01-15T12:00:00Z' tweets: - id: '1234567890' text: &launch-text 'Just launched our new feature!' style2: xUsername: 'BillGates' tweetCount: 40 isOwnAccount: false fetchedAt: '2025-01-15T12:00:00Z' tweets: - id: '9876543210' text: 'Climate change is a global challenge.' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /styles/{id}: get: operationId: getStyle description: Returns 1 cached writing style profile. summary: Get cached style profile tags: [Composition] security: *api-auth parameters: &style-id-parameters - $ref: '#/components/parameters/StyleId' responses: '200': description: Style profile content: *style-profile-content-with-example '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response put: operationId: saveStyle description: Creates or replaces a style profile from supplied posts. summary: Save style profile with custom tweets tags: [Composition] security: *api-auth parameters: *style-id-parameters requestBody: required: true description: Sample tweets that define the style profile. content: application/json: schema: type: object required: [tweets] properties: label: type: string maxLength: 50 description: Optional display label of up to 50 characters. When sent, it must match the path ID, ignoring case and a leading @. When it is left out, the path ID names the style and must fit the same limit. example: 'Professional Voice' tweets: type: array minItems: 1 maxItems: 100 items: type: object required: [text] properties: text: type: string maxLength: 25000 example: 'Excited to share our latest research.' description: Array of tweet objects example: - text: &research-text 'Excited to share our latest research.' example: label: 'Professional Voice' tweets: - text: *research-text responses: '200': description: Style profile saved content: application/json: schema: $ref: '#/components/schemas/StyleProfile' example: xUsername: 'professional voice' tweetCount: 1 isOwnAccount: false fetchedAt: '2026-08-02T18:30:00.000Z' tweets: - id: '0' text: *research-text authorUsername: 'professional voice' createdAt: '2026-08-02T18:30:00.000Z' '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response delete: operationId: deleteStyle description: Permanently removes 1 cached style profile. summary: Delete a style profile tags: [Composition] security: *api-auth parameters: *style-id-parameters responses: '204': $ref: '#/components/responses/NoContent' '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /styles/{id}/performance: get: operationId: getStylePerformance description: Returns engagement metrics for an analyzed public X profile. summary: Get engagement metrics for style tweets tags: [Composition] security: *api-auth parameters: *style-id-parameters responses: '200': description: Performance metrics content: application/json: schema: type: object required: [xUsername, tweetCount, tweets] properties: xUsername: *handle-example-schema tweetCount: type: integer minimum: 0 example: 5 tweets: type: array items: type: object required: [id, text] properties: id: &tweet-id-example-schema type: string example: '1234567890' text: type: string example: 'Excited to share our latest research.' likeCount: type: integer minimum: 0 example: 120 retweetCount: type: integer minimum: 0 example: 15 replyCount: type: integer minimum: 0 example: 8 quoteCount: type: integer minimum: 0 example: 3 bookmarkCount: type: integer minimum: 0 example: 42 viewCount: type: integer minimum: 0 example: 5000 example: - id: '1234567890' text: *research-text likeCount: 120 retweetCount: 15 replyCount: 8 quoteCount: 3 bookmarkCount: 42 viewCount: 5000 '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '404': *not-found-response '422': $ref: '#/components/responses/InvalidInput' '429': *rate-limit-exceeded-response /radar: get: operationId: getRadar description: Returns current topics and sources for writing research. summary: Get trending topics from curated sources tags: [Composition] security: *api-auth parameters: - name: after in: query schema: type: string maxLength: 128 description: Cursor for pagination, from the prior response's nextCursor. A cursor the radar can't read gets 400 `invalid_input`. - name: category in: query schema: type: string enum: &radar-category-values [ general, tech, dev, science, culture, politics, business, entertainment, ] description: Filter by category. - name: hours in: query schema: type: integer minimum: 1 maximum: 72 default: 6 description: Lookback window in hours (1-72, default 6). - name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 50 description: Number of items to return (1-100, default 50). - name: region in: query schema: type: string maxLength: 100 default: global description: Region filter. Use `global` or a region code such as `US`, `GB`, `TR`, or `ES`. - name: source in: query schema: type: string enum: &radar-source-values [ github, google_trends, hacker_news, polymarket, reddit, trustmrr, wikipedia, ] description: 'Source filter. One of github, google_trends, hacker_news, polymarket, reddit, trustmrr or wikipedia.' responses: '200': description: Radar items content: application/json: schema: type: object required: [hasMore, items] properties: hasMore: *boolean-example-false items: type: array items: $ref: '#/components/schemas/RadarItem' example: [] nextCursor: type: string description: Opaque cursor for the next page (present only when hasMore is true). example: 'eyJ0IjoxNzM5OTcyODAwLCJpIjoiOTk5In0=' example: hasMore: false items: [] '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response # ── Monitors ───────────────────────────────────────────── /monitors: get: operationId: listMonitors description: Returns account monitors with their current operating states. summary: List monitors tags: [Monitors] security: *api-auth parameters: *list-limit-after-parameters responses: '200': description: Monitor list content: application/json: schema: type: object required: [monitors, total, hasMore] properties: monitors: type: array items: $ref: '#/components/schemas/Monitor' example: [] total: description: Account monitors on this page. type: integer minimum: 0 example: 0 hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: monitors: [] total: 0 hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createMonitor summary: Create monitor description: Creates an account monitor, with no count limit. Active monitors check every second for 30 credits an hour, events & webhook deliveries included. That hourly price is a monitor's only charge. Creation needs the credits of the first hour. tags: [Monitors] security: &api-auth-2 [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Target X username or user ID and event types to monitor. content: application/json: schema: type: object required: [username, eventTypes] properties: username: type: string maxLength: 19 pattern: '^(@?[A-Za-z0-9_]{1,15}|[0-9]{1,19})$' description: X username to monitor, with or without @, or the account's numeric user ID. A number is a user ID. The monitor shows the username X shows for the account. example: elonmusk name: type: string minLength: 1 maxLength: 80 description: Your label for the monitor. Its events carry it as monitorName. Xquik normalizes whitespace. example: Launch watch eventTypes: &event-types type: array $ref: '#/components/schemas/EventTypeArray' example: [tweet.new, tweet.reply] example: username: 'elonmusk' name: 'Launch watch' eventTypes: - 'tweet.new' - 'tweet.reply' responses: '201': description: Monitor created content: application/json: schema: type: object required: [ id, username, xUserId, eventTypes, isActive, createdAt, nextBillingAt, ] properties: id: *resource-id-example-schema username: *handle-example-schema xUserId: *tweet-id-example-schema eventTypes: *event-types isActive: &boolean-example-true type: boolean example: true createdAt: *created-at-schema nextBillingAt: type: string format: date-time description: Next hourly credit charge time. New active monitors are due immediately. example: '2025-01-15T12:00:00Z' example: id: '42' username: elonmusk xUserId: '1234567890' eventTypes: [tweet.new, tweet.reply] isActive: true createdAt: '2025-01-15T12:00:00Z' nextBillingAt: '2025-01-15T12:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '402': *payment-required-response '404': &user-not-found-response $ref: '#/components/responses/UserNotFound' '409': description: Monitor already exists content: application/json: schema: &error-schema $ref: '#/components/schemas/Error' example: error: 'monitor_already_exists' message: 'Monitor already exists.' '429': *rate-limit-exceeded-response /monitors/keywords: get: operationId: listKeywordMonitors description: Returns keyword monitors with their current operating states. summary: List keyword monitors tags: [Monitors] security: *api-auth parameters: *list-limit-after-parameters responses: '200': description: Keyword monitor list content: application/json: schema: type: object required: [monitors, total, hasMore] properties: monitors: type: array items: $ref: '#/components/schemas/KeywordMonitor' example: [] total: description: Keyword monitors on this page. type: integer minimum: 0 example: 0 hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: monitors: [] total: 0 hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createKeywordMonitor summary: Create keyword monitor description: Creates a keyword monitor, with no count limit. Active monitors check every second for 30 credits an hour, events & webhook deliveries included. That hourly price is a monitor's only charge. Creation needs the credits of the first hour. tags: [Monitors] security: *api-auth-2 requestBody: required: true description: Search query and event types to monitor. content: application/json: schema: type: object required: [query, eventTypes] properties: query: type: string minLength: 1 maxLength: 512 description: X search query to monitor. Xquik normalizes whitespace. example: 'xquik OR "x api"' name: type: string minLength: 1 maxLength: 80 description: Your own label for the keyword monitor. Its events carry it as monitorName. example: Launch mentions eventTypes: &single-event-type type: array $ref: '#/components/schemas/EventTypeArray' example: [tweet.new] example: query: 'xquik OR "x api"' name: 'Launch mentions' eventTypes: - 'tweet.new' responses: '201': description: Keyword monitor created content: application/json: schema: $ref: '#/components/schemas/KeywordMonitor' example: id: '21' query: 'xquik OR "x api"' eventTypes: [tweet.new] isActive: true createdAt: '2025-01-15T12:00:00Z' nextBillingAt: '2025-01-15T12:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '402': *payment-required-response '409': description: Keyword monitor already exists content: application/json: schema: *error-schema example: error: 'monitor_already_exists' message: 'Monitor already exists.' '429': *rate-limit-exceeded-response /monitors/keywords/{id}: get: operationId: getKeywordMonitor description: Returns configuration and status for 1 keyword monitor. summary: Get keyword monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': description: Keyword monitor details content: &keyword-monitor-content application/json: schema: $ref: '#/components/schemas/KeywordMonitor' example: id: '21' query: 'xquik OR "x api"' eventTypes: [tweet.new] isActive: true createdAt: '2025-01-15T12:00:00Z' nextBillingAt: '2025-01-15T13:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response patch: operationId: updateKeywordMonitor description: Updates a keyword monitor's event types or active state. A monitor turned on again starts from that moment, with no event for a post made while it was off. Read those posts with the search route. summary: Update keyword monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters requestBody: required: true description: Updated event types or active status. content: application/json: schema: type: object properties: eventTypes: *single-event-type isActive: *boolean-example-true name: type: [string, 'null'] minLength: 1 maxLength: 80 description: New label for the keyword monitor. Send null to remove it. example: Launch mentions example: eventTypes: - 'tweet.new' isActive: true name: 'Launch mentions' responses: '200': description: Keyword monitor updated content: *keyword-monitor-content '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response delete: operationId: deleteKeywordMonitor description: Stops 1 keyword monitor, then removes its stored events in bounded batches. Poll statusUrl until the monitor returns 404. summary: Delete keyword monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters responses: &monitor-deletion-responses '202': $ref: '#/components/responses/MonitorDeletionAccepted' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response /monitors/{id}: get: operationId: getMonitor description: Returns configuration and status for 1 account monitor. summary: Get monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': description: Monitor details content: application/json: schema: $ref: '#/components/schemas/Monitor' example: id: '42' username: elonmusk xUserId: '1234567890' eventTypes: [tweet.new, tweet.reply] isActive: true createdAt: '2025-01-15T12:00:00Z' nextBillingAt: '2025-01-15T13:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response patch: operationId: updateMonitor description: Updates an account monitor's event types or active state. A monitor turned on again starts from that moment, with no event for a post made while it was off. Read those posts with the timeline & search routes. summary: Update monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters requestBody: required: true description: Event type list or active state for the account monitor. content: application/json: schema: type: object properties: eventTypes: *single-event-type isActive: *boolean-example-true name: type: [string, 'null'] minLength: 1 maxLength: 80 description: New label for the account monitor. Send null to remove the label. example: Launch watch example: eventTypes: - 'tweet.new' isActive: true name: 'Launch watch' responses: '200': description: Monitor updated content: application/json: schema: $ref: '#/components/schemas/Monitor' example: id: '42' username: elonmusk xUserId: '1234567890' eventTypes: [tweet.new] isActive: true createdAt: '2025-01-15T12:00:00Z' nextBillingAt: '2025-01-15T13:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '409': description: The monitored X account is still unavailable content: application/json: schema: *error-schema example: error: monitor_profile_unavailable message: X account is gone or private. Resume once it is back & public. '429': *rate-limit-exceeded-response delete: operationId: deleteMonitor description: Stops 1 account monitor, then removes its stored events in bounded batches. Poll statusUrl until the monitor returns 404. summary: Delete monitor tags: [Monitors] security: *api-auth-2 parameters: *resource-id-parameters responses: *monitor-deletion-responses # ── Events ─────────────────────────────────────────────── /events: get: operationId: listEvents description: Returns monitor events with cursor pagination and filters. summary: List events tags: [Events] security: *api-auth-2 parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/After' - name: monitorId in: query description: Account monitor ID. The monitor_id alias also works. schema: type: string maxLength: 32 - name: keywordMonitorId in: query description: Keyword monitor ID. The keyword_monitor_id alias also works. schema: type: string maxLength: 32 - name: eventType in: query description: Filter events by type schema: $ref: '#/components/schemas/EventType' responses: '200': description: Event list content: application/json: schema: type: object required: [events, hasMore] properties: events: type: array items: $ref: '#/components/schemas/Event' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: events: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response /events/stream: get: operationId: streamEvents description: > Streams the account's monitor events as server-sent events, each named by its event type and numbered by its event ID. A reconnect that sends Last-Event-ID first gets every event after that one from the last 30 days, then each new event. A connection lasts up to 30 minutes and sends a comment every 15 seconds while idle. Keep up to 5 streams open per account. Events and streams cost no credits. summary: Stream events tags: [Events] security: *api-auth-2 parameters: - name: Last-Event-ID in: header description: The last event ID the client got. The stream first sends every event after it. A value that is not an event ID counts as no header. schema: type: string maxLength: 32 example: '42' responses: '200': description: Server-sent events. Each event's data line holds 1 Event as JSON. content: text/event-stream: schema: type: string example: |- id: 42 event: tweet.new data: {"id":"42","type":"tweet.new","monitorId":"7","monitorType":"account","occurredAt":"2025-01-15T12:00:00.000Z","data":{}} '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '429': description: > The account has 5 streams open, or used Xquik's read limit. Close a stream, or wait `Retry-After` seconds. headers: RateLimit: { $ref: '#/components/headers/RateLimit' } RateLimit-Policy: { $ref: '#/components/headers/RateLimitPolicy' } Retry-After: description: Seconds to wait before a retry, sent with the read limit. schema: type: integer minimum: 1 content: application/json: schema: allOf: - $ref: '#/components/schemas/Error' - type: object properties: retryAfter: type: integer minimum: 0 example: 60 examples: tooManyStreams: summary: 5 streams open value: error: 'too_many_streams' message: 'Close a stream first. Keep up to 5 open per account.' xquikLimit: summary: Xquik limit value: error: 'rate_limit_exceeded' message: 'Too many requests. Try again later.' retryAfter: 60 /events/{id}: get: operationId: getEvent description: Returns 1 monitor event owned by the account. summary: Get event tags: [Events] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': description: Event details content: application/json: schema: $ref: '#/components/schemas/EventDetail' example: id: '42' type: 'tweet.new' username: 'elonmusk' monitorId: '7' monitorType: account occurredAt: '2025-01-15T12:00:00Z' data: tweetId: '1234567890' '401': *unauthenticated-response '400': *invalid-input-response '404': *not-found-response '429': *rate-limit-exceeded-response # ── Extractions ────────────────────────────────────────── /extractions: get: operationId: listExtractions description: Returns extraction jobs with status and result counts. summary: List extraction jobs tags: [Extractions] security: *api-auth-2 parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/After' - name: toolType in: query description: Filter by extraction tool type schema: $ref: '#/components/schemas/ExtractionToolType' - name: status in: query description: Filter by job status schema: type: string enum: [pending, running, canceled, completed, failed] responses: '200': description: Extraction job list content: application/json: schema: type: object required: [extractions, hasMore] properties: extractions: type: array items: $ref: '#/components/schemas/ExtractionJob' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: extractions: [] hasMore: false '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createExtraction description: Starts 1 single-target or multi-target extraction. Follow waitUrl, then page statusUrl once it completes. summary: Create extraction tags: [Extractions] security: *api-auth-2 parameters: - $ref: '#/components/parameters/IdempotencyKey' - name: dry_run in: query description: Estimate cost without creating an extraction. schema: &boolean-default-false type: boolean default: false example: true requestBody: required: true description: Tool type plus 1 or more tweet, user, community, list, or search targets. content: application/json: schema: $ref: '#/components/schemas/ExtractionRequest' examples: followers: &extraction-followers-example summary: 'Followers, with profile filters' value: toolType: 'follower_explorer' targetUsername: 'NASA' enrichProfiles: true minFollowers: 1000 maxFollowers: 1000000 minFollowing: 10 maxFollowing: 5000 minPosts: 100 maxPosts: 100000 minAccountAgeDays: 365 verifiedType: 'Business' hasWebsite: true hasLocation: true hasEmail: true businessEmailOnly: true emailDomains: 'nasa.gov' bioContains: 'space, astronomy' locationContains: 'Houston' usernameContains: 'space' resultsLimit: 500 following: &extraction-following-example summary: 'Accounts a user follows' value: toolType: 'following_explorer' targetUsername: 'NASA' resultsLimit: 200 verifiedFollowers: &extraction-verifiedFollowers-example summary: 'Verified followers' value: toolType: 'verified_follower_explorer' targetUsername: 'NASA' resultsLimit: 200 relations: &extraction-relations-example summary: 'Followers & following of several accounts, merged' value: toolType: 'follower_explorer' relationTargets: - relation: 'followers' value: 'NASA' - relation: 'following' value: 'SpaceX' dedupeAcrossTargets: true dedupeMode: 'merge' overlapMode: true includeTargetMetadata: true maxItemsPerTarget: 500 resultsLimit: 1000 posts: &extraction-posts-example summary: "A user's posts" value: toolType: 'post_extractor' targetUsername: 'NASA' resultsLimit: 100 postsOfSeveral: &extraction-postsOfSeveral-example summary: 'Posts of several users' value: toolType: 'post_extractor' targetUsernames: - 'NASA' - 'SpaceX' - 'esa' resultsLimit: 300 media: &extraction-media-example summary: "A user's media posts" value: toolType: 'user_media' targetUsername: 'NASA' resultsLimit: 100 likes: &extraction-likes-example summary: "A user's likes" value: toolType: 'user_likes' targetUsername: 'NASA' resultsLimit: 100 mentions: &extraction-mentions-example summary: 'Posts that mention a user' value: toolType: 'mention_extractor' targetUsername: 'NASA' resultsLimit: 100 replies: &extraction-replies-example summary: 'Replies to a post, newest first' value: toolType: 'reply_extractor' targetTweetId: '2082577277246972300' collectionStrategy: 'auto' scope: 'all' maxDepth: 2 sort: 'latest' excludeOriginalAuthor: true includeOriginalPost: true hasMediaOnly: false sinceTime: '2026-09-01T00:00:00Z' untilTime: '2026-09-30T23:59:59Z' maxPagesPerTarget: 5 startCursor: 'xqcv1_tkGoEx1UJRqeog9a2BJdmzUZTMCoU_M8kb' resultsLimit: 500 quotes: &extraction-quotes-example summary: 'Quotes of a post' value: toolType: 'quote_extractor' targetTweetId: '2102882545427714266' resultsLimit: 100 quotesOfSeveral: &extraction-quotesOfSeveral-example summary: 'Quotes of several posts' value: toolType: 'quote_extractor' targetTweetIds: - '2102882545427714266' - '2102761519985332442' resultsLimit: 200 reposters: &extraction-reposters-example summary: 'Accounts that reposted a post' value: toolType: 'repost_extractor' targetTweetId: '2106061652617568263' resultsLimit: 200 likers: &extraction-likers-example summary: 'Accounts that liked a post' value: toolType: 'favoriters' targetTweetId: '2102882545427714266' resultsLimit: 200 thread: &extraction-thread-example summary: "A post's thread" value: toolType: 'thread_extractor' targetTweetId: '2102882545427714266' article: &extraction-article-example summary: 'An X Article' value: toolType: 'article_extractor' targetTweetId: '2002118205729562949' communityMembers: &extraction-communityMembers-example summary: 'Community members' value: toolType: 'community_extractor' targetCommunityId: '1493446837214187523' resultsLimit: 200 communityModerators: &extraction-communityModerators-example summary: 'Community moderators' value: toolType: 'community_moderator_explorer' targetCommunityId: '1493446837214187523' communityPosts: &extraction-communityPosts-example summary: 'Posts in several Communities' value: toolType: 'community_post_extractor' targetCommunityIds: - '1493446837214187523' resultsLimit: 200 communitySearch: &extraction-communitySearch-example summary: 'A search inside a Community' value: toolType: 'community_search' targetCommunityId: '1493446837214187523' searchQuery: 'startup' language: 'en' sinceDate: '2026-09-01' untilDate: '2026-09-30' resultsLimit: 100 listMembers: &extraction-listMembers-example summary: 'List members' value: toolType: 'list_member_extractor' targetListId: '4143408' listFollowers: &extraction-listFollowers-example summary: 'List followers' value: toolType: 'list_follower_explorer' targetListId: '4143408' resultsLimit: 200 listPosts: &extraction-listPosts-example summary: "A List's posts" value: toolType: 'list_post_extractor' targetListId: '4143408' resultsLimit: 200 space: &extraction-space-example summary: "A Space's hosts, speakers & listeners" value: toolType: 'space_explorer' targetSpaceId: '1OGwblLjnQMKB' people: &extraction-people-example summary: 'A people search' value: toolType: 'people_search' searchQuery: 'astronomy' enrichProfiles: true resultsLimit: 100 search: &extraction-search-example summary: 'A post search with engagement filters' value: toolType: 'tweet_search_extractor' searchQuery: 'Artemis' queryType: 'Top' fromUser: 'NASA' language: 'en' sinceDate: '2026-09-01' untilDate: '2026-09-30' mediaType: 'images' minFaves: 100 minRetweets: 10 minReplies: 5 minQuotes: 1 minViews: 10000 minBookmarks: 5 maxLikes: 1000000 maxRetweets: 100000 maxReplies: 100000 maxQuotes: 10000 verifiedOnly: true blueVerifiedOnly: false replies: 'exclude' retweets: 'exclude' quotes: 'include' nativeRetweets: false safe: true news: false resultsLimit: 200 searchWords: &extraction-searchWords-example summary: 'A post search by words & links' value: toolType: 'tweet_search_extractor' searchQuery: 'moon' queryType: 'Latest' exactPhrase: 'Artemis II' excludeWords: 'rumor' anyWords: 'launch, crew' hashtags: '#Artemis' cashtags: '$BA' url: 'nasa.gov' cardName: 'summary_large_image' toUser: 'NASA' mentioning: 'NASA' withinTime: '7d' sinceId: '2102000000000000000' maxId: '2102882545427714266' advancedQuery: 'filter:links' resultsLimit: 200 searchNear: &extraction-searchNear-example summary: 'A post search near a place' value: toolType: 'tweet_search_extractor' searchQuery: 'launch' near: 'Cape Canaveral' placeCountry: 'US' resultsLimit: 100 searchArea: &extraction-searchArea-example summary: 'A post search inside an area' value: toolType: 'tweet_search_extractor' searchQuery: 'launch' place: '5e02a0f0d91c76d2' pointRadius: '-80.60 28.39 25mi' boundingBox: '-81.0 28.0 -80.4 28.8' resultsLimit: 100 searchConversation: &extraction-searchConversation-example summary: 'Replies, quotes & reposts of a post' value: toolType: 'tweet_search_extractor' searchQuery: 'Artemis' conversationId: '2102882545427714266' inReplyToTweetId: '2102882545427714266' quotesOfTweetId: '2102882545427714266' retweetsOfTweetId: '2102882545427714266' listId: '4143408' resultsLimit: 100 searchCollection: &extraction-searchCollection-example summary: 'Several searches, accounts, Lists & posts in 1 job' value: toolType: 'tweet_search_extractor' searchQueries: - 'Artemis' - 'Starship' targetUsernames: - 'NASA' - 'SpaceX' targetListIds: - '4143408' targetTweetIds: - '2102882545427714266' targets: - kind: 'profile' value: 'NASA' - kind: 'replies' value: '2082577277246972300' includeSearchTerms: true dedupeAcrossTargets: true maxItemsPerTarget: 100 resultsLimit: 500 responses: '200': description: Dry-run estimate headers: &deprecated-search-headers Deprecation: { $ref: '#/components/headers/Deprecation' } Link: { $ref: '#/components/headers/DeprecationLink' } Sunset: { $ref: '#/components/headers/Sunset' } content: application/json: schema: $ref: '#/components/schemas/ExtractionEstimate' '202': description: Extraction started. The Location header holds its result URL. headers: Location: description: Relative extraction result URL. schema: { type: string } Retry-After: description: Seconds before polling statusUrl. schema: &whole-number $ref: '#/components/schemas/WholeNumber' Idempotency-Replayed: description: Present as true when returning the original job. schema: { type: string, const: 'true' } Deprecation: { $ref: '#/components/headers/Deprecation' } Link: { $ref: '#/components/headers/DeprecationLink' } Sunset: { $ref: '#/components/headers/Sunset' } content: application/json: schema: type: object required: [id, pollAfterMs, status, statusUrl, toolType, waitUrl] properties: id: { type: string, example: 'ext_123' } pollAfterMs: { type: integer, minimum: 0, example: 1000 } statusUrl: { type: string, example: '/api/v1/extractions/a1b2c3d4' } waitUrl: &extraction-wait-url type: string example: >- /api/v1/extractions/id?wait=10&limit=1&outputMode=compact toolType: $ref: '#/components/schemas/ExtractionToolType' status: type: string enum: [pending, running, canceled, completed, failed] example: running '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTarget' '404': *not-found-response '409': { $ref: '#/components/responses/IdempotencyConflict' } '424': &x-api-error-response $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response '502': *x-api-error-response /extractions/estimate: post: operationId: estimateExtraction x-mcp-annotations: { readOnlyHint: true } description: Estimates extraction cost without creating a job. summary: Estimate extraction cost tags: [Extractions] security: *api-auth-2 requestBody: required: true description: Takes the same parameters as a real extraction. Returns the estimated credit cost without running the job. content: application/json: schema: $ref: '#/components/schemas/ExtractionRequest' examples: followers: *extraction-followers-example following: *extraction-following-example verifiedFollowers: *extraction-verifiedFollowers-example relations: *extraction-relations-example posts: *extraction-posts-example postsOfSeveral: *extraction-postsOfSeveral-example media: *extraction-media-example likes: *extraction-likes-example mentions: *extraction-mentions-example replies: *extraction-replies-example quotes: *extraction-quotes-example quotesOfSeveral: *extraction-quotesOfSeveral-example reposters: *extraction-reposters-example likers: *extraction-likers-example thread: *extraction-thread-example article: *extraction-article-example communityMembers: *extraction-communityMembers-example communityModerators: *extraction-communityModerators-example communityPosts: *extraction-communityPosts-example communitySearch: *extraction-communitySearch-example listMembers: *extraction-listMembers-example listFollowers: *extraction-listFollowers-example listPosts: *extraction-listPosts-example space: *extraction-space-example people: *extraction-people-example search: *extraction-search-example searchWords: *extraction-searchWords-example searchNear: *extraction-searchNear-example searchArea: *extraction-searchArea-example searchConversation: *extraction-searchConversation-example searchCollection: *extraction-searchCollection-example responses: '200': description: Extraction estimate headers: *deprecated-search-headers content: application/json: schema: $ref: '#/components/schemas/ExtractionEstimate' '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTarget' '404': *not-found-response '424': *x-api-error-response '429': *rate-limit-exceeded-response /extractions/{id}: delete: operationId: cancelExtraction description: Cancels an active extraction without charging or saving rows. summary: Cancel extraction tags: [Extractions] security: *api-auth-2 parameters: - $ref: '#/components/parameters/ExtractionId' responses: '200': description: Extraction canceled content: application/json: schema: type: object required: [id, status] properties: id: { type: string, example: 'aB3dE6gH9jK2' } status: { type: string, const: canceled } '401': *unauthenticated-response '404': *not-found-response '409': description: Extraction already reached a terminal state content: { application/json: { schema: { $ref: '#/components/schemas/Error' } }, } '429': *rate-limit-exceeded-response get: operationId: getExtraction description: Returns status and up to 1,000 results. Follow nextCursor when hasMore is true. summary: Get extraction results tags: [Extractions] security: *api-auth-2 parameters: - $ref: '#/components/parameters/ExtractionId' - name: limit in: query description: Maximum results per page (1-1000, default 100). schema: type: integer minimum: 1 maximum: 1000 default: 100 - $ref: '#/components/parameters/After' - name: wait in: query description: Wait up to this many seconds when the job is active. schema: { type: integer, minimum: 0, maximum: 10, default: 0 } - name: outputMode in: query description: Use compact for core fields and tweet counts, full for nested enrichment, or raw for a source copy. schema: type: string enum: [compact, full, raw] default: full - name: outputPreset in: query description: Keep enrichment nested or merge it into each result. schema: type: string enum: [nested, flat] default: nested - name: fieldStyle in: query description: Preserve source keys or convert result field names. schema: type: string enum: [source, camelCase, snake_case] default: source - name: includeRaw in: query deprecated: true description: Use outputMode=raw instead. schema: *boolean-default-false responses: '200': description: Extraction job with results headers: *deprecated-read-headers content: application/json: schema: type: object required: [job, results, hasMore, pollAfterMs, waitUrl] properties: job: { $ref: '#/components/schemas/ExtractionJob' } results: type: array items: { $ref: '#/components/schemas/ExtractionResult' } example: [] hasMore: { type: boolean, example: false } pollAfterMs: { type: integer, minimum: 0, example: 0 } waitUrl: *extraction-wait-url nextCursor: { type: string, example: 'abc123' } example: job: id: 'ext_123' toolType: follower_explorer status: completed totalResults: 0 createdAt: '2026-08-23T10:00:00Z' completedAt: '2026-08-23T10:00:05Z' results: [] hasMore: false pollAfterMs: 0 waitUrl: '/api/v1/extractions/ext_123?wait=10&limit=1&outputMode=compact' '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /extractions/{id}/export: get: operationId: exportExtraction x-mcp-exclusion-reason: &binary-rest Binary downloads remain direct REST. description: Downloads completed extraction results in the requested format. JSON rows also keep each result's nested `enrichmentData`, as `GET /extractions/{id}` returns it. summary: Export extraction results tags: [Extractions] security: *api-auth-2 parameters: - $ref: '#/components/parameters/ExtractionId' - name: format in: query required: true description: Export file format schema: type: string enum: [csv, json, md, md-document, pdf, txt, xlsx] - name: minFollowers in: query schema: *whole-number description: Minimum follower count. - name: maxFollowers in: query schema: *whole-number description: Maximum follower count. - name: minFollowing in: query schema: *whole-number description: Minimum following count. - name: maxFollowing in: query schema: *whole-number description: Maximum following count. - name: minPosts in: query schema: *whole-number description: Minimum post count. - name: maxPosts in: query schema: *whole-number description: Maximum post count. - name: minLikes in: query schema: *whole-number description: Minimum like count. - name: minReplies in: query schema: *whole-number description: Minimum reply count. - name: minRetweets in: query schema: *whole-number description: Minimum repost count. - name: minViews in: query schema: *whole-number description: Minimum view count. - name: hasDescription in: query schema: { type: boolean } description: Require a non-empty description. - name: hasLocation in: query schema: { type: boolean } description: Require a non-empty location. - name: hasEmail in: query schema: { type: boolean } description: Require an email in the row's Email column. - name: businessEmailOnly in: query schema: { type: boolean } description: > Require an email outside free webmail, such as Gmail, in the row's Email column. - name: emailDomains in: query schema: { type: string, maxLength: 4096 } description: > Require the row's email at one of these domains. Separate domains with commas. Subdomains match. example: acme.com,stanford.edu - name: hasMedia in: query schema: { type: boolean } description: Require media. - name: verified in: query schema: { type: boolean } description: Filter by verified status. - name: lang in: query schema: { type: string, maxLength: 35 } description: Filter by language code. - name: search in: query schema: { type: string, maxLength: 512 } description: Search exported result text. - name: sinceDate in: query schema: { type: string, format: date, maxLength: 64 } description: Include results on or after this date, from 00:00 UTC. An ISO 8601 time starts at that instant. The filter drops results without a post date. An empty value sets no filter. - name: untilDate in: query schema: { type: string, format: date, maxLength: 64 } description: Include results on or before this date, inclusive, through 23:59:59 UTC. An ISO 8601 time ends at that instant. The filter drops results without a post date. An empty value sets no filter. responses: '200': description: Exported file content: &binary-download-content application/octet-stream: schema: type: string format: binary '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response # ── Draws ──────────────────────────────────────────────── /draws: get: operationId: listDraws description: Returns giveaway draws owned by the authenticated account. summary: List draws tags: [Draws] security: *api-auth-2 parameters: &limit-after-parameters - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/After' responses: '200': description: Draw list content: application/json: schema: type: object required: [draws, hasMore] properties: draws: type: array items: $ref: '#/components/schemas/DrawListItem' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: draws: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createDraw summary: Run giveaway draw description: Checks credits, then draws winners from inspected replies & reposters. Remaining credits cap the candidates. tags: [Draws] security: *api-auth-2 parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true description: Tweet URL, winner count & optional eligibility filters for retweet, follow, keywords, hashtags & account age. content: application/json: schema: type: object required: [tweetUrl] properties: tweetUrl: type: string format: uri maxLength: 2048 example: 'https://x.com/elonmusk/status/1234567890' winnerCount: type: integer minimum: 1 default: 1 example: 3 backupCount: type: integer minimum: 0 example: 2 uniqueAuthorsOnly: *boolean-example-true mustRetweet: *boolean-example-true mustFollowUsername: type: string maxLength: 19 pattern: '^(@?[A-Za-z0-9_]{1,15}|[0-9]{1,19})$' description: X username entrants must follow, with or without @, or the account's numeric user ID. A number is a user ID. example: elonmusk filterMinFollowers: type: integer minimum: 0 example: 50 filterAccountAgeDays: type: integer minimum: 0 example: 30 filterLanguage: type: string maxLength: 35 example: en requiredHashtags: type: array maxItems: 25 items: type: string maxLength: 100 example: ['#giveaway'] requiredKeywords: type: array maxItems: 25 items: type: string maxLength: 100 example: ['entered'] requiredMentions: type: array maxItems: 25 items: type: string maxLength: 100 example: ['@elonmusk'] example: tweetUrl: 'https://x.com/elonmusk/status/1234567890' winnerCount: 3 backupCount: 2 uniqueAuthorsOnly: true mustRetweet: true mustFollowUsername: 'elonmusk' filterMinFollowers: 50 filterAccountAgeDays: 30 filterLanguage: 'en' requiredHashtags: - '#giveaway' requiredKeywords: - 'entered' requiredMentions: - '@elonmusk' responses: '201': description: Draw completed headers: Idempotency-Replayed: description: Present as true when returning the original draw. schema: { type: string, const: 'true' } content: application/json: schema: type: object required: [id, tweetId, totalEntries, validEntries, winners] properties: id: type: string example: 'f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345' tweetId: *tweet-id-example-schema totalEntries: type: integer minimum: 0 description: Entries inspected after the credit cap, which can be fewer than the post's replies. example: 250 validEntries: type: integer minimum: 0 description: Inspected entries that passed every filter. A credit cap can leave valid replies uninspected. example: 200 winners: type: array items: $ref: '#/components/schemas/Winner' example: [] example: id: 'f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345' tweetId: '1234567890' totalEntries: 250 validEntries: 200 winners: [] '400': *invalid-input-response '401': *unauthenticated-response '402': description: Not enough usable credits. A draw fails before it runs when the balance cannot cover the minimum cost. It also fails after it runs when Xquik cannot deduct its final cost. Xquik saves & charges nothing. content: application/json: schema: *error-schema example: error: 'insufficient_credits' message: 'Insufficient credits' '404': *not-found-response '409': description: Idempotency-Key belongs to another draw request, or its first request still runs. Xquik charges nothing for it. content: application/json: schema: *error-schema examples: conflict: summary: Another request body value: error: idempotency_conflict message: Idempotency-Key belongs to another request. Use a new key. inProgress: summary: First request still running value: error: idempotency_in_progress message: Idempotency-Key belongs to a running request. Retry later. '424': description: >- X failed or stopped early. Retry after replies_incomplete or retweeters_incomplete. draw_too_large means the post has more entries than 1 draw reads. Contact support. Xquik saves & charges nothing. content: application/json: schema: *error-schema example: error: replies_incomplete message: X stopped before every reply loaded. Retry the draw later. '429': *rate-limit-exceeded-response '502': *x-api-error-response /draws/{id}: get: operationId: getDraw description: Returns draw rules, status, candidates, and selected winners. summary: Get draw details tags: [Draws] security: *api-auth-2 parameters: - $ref: '#/components/parameters/DrawId' responses: '200': description: Draw with winners content: application/json: schema: type: object required: [draw, winners] properties: draw: type: object $ref: '#/components/schemas/DrawDetail' example: &draw-detail-example id: 'f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345' tweetUrl: 'https://x.com/elonmusk/status/1234567890' tweetId: '1234567890' tweetText: 'Giving away 3 Tesla Model 3s!' tweetAuthorUsername: 'elonmusk' status: 'completed' totalEntries: 250 validEntries: 200 tweetLikeCount: 50000 tweetRetweetCount: 25000 tweetReplyCount: 10000 tweetQuoteCount: 5000 createdAt: '2025-01-15T12:00:00Z' winners: type: array items: $ref: '#/components/schemas/Winner' example: [] example: draw: *draw-detail-example winners: [] '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /draws/{id}/export: get: operationId: exportDraw x-mcp-exclusion-reason: *binary-rest description: Downloads draw evidence in the requested format. summary: Export draw data tags: [Draws] security: *api-auth-2 parameters: - $ref: '#/components/parameters/DrawId' - name: format in: query required: true description: >- Export output format. PDF entry exports include up to 10,000 rows. Other entry formats include up to 100,000 rows. schema: type: string enum: [csv, json, md, md-document, pdf, txt, xlsx] - name: type in: query schema: type: string enum: [winners, entries] default: winners description: Export winners or all entries responses: '200': description: Exported draw file content: *binary-download-content '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response # ── Webhooks ───────────────────────────────────────────── /webhooks: get: operationId: listWebhooks description: Returns configured webhook endpoints and delivery states. summary: List webhooks tags: [Webhooks] security: *api-auth parameters: *list-limit-after-parameters responses: '200': description: Webhook list content: application/json: schema: type: object required: [webhooks, hasMore] properties: webhooks: type: array items: $ref: '#/components/schemas/Webhook' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: webhooks: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response post: operationId: createWebhook description: Registers an endpoint for signed event deliveries. summary: Create webhook tags: [Webhooks] security: *api-auth-2 requestBody: required: true description: HTTPS callback URL and event types to subscribe to. content: application/json: schema: type: object required: [url, eventTypes] properties: url: type: string format: uri maxLength: 2048 description: > HTTPS URL. A Discord channel webhook or a Slack incoming webhook URL gets chat messages. The events of 1 post come as 1 alert, & alerts that wait together as 1 digest. A busy channel gets 5 quick messages, then 1 every 30 s. To deliver to Telegram, use POST /webhooks/telegram instead. example: 'https://example.com/webhook' eventTypes: *event-types example: url: 'https://example.com/webhook' eventTypes: [tweet.new, tweet.reply] responses: '201': description: Webhook created content: application/json: schema: type: object required: [id, url, secret, eventTypes, createdAt] properties: ignoredFields: $ref: '#/components/schemas/IgnoredFieldsNotice/properties/ignoredFields' id: *resource-id-example-schema url: type: string format: uri example: 'https://example.com/webhook' secret: type: string description: Plaintext HMAC signing secret returned only at creation. example: 'abababababababababababababababababababababababababababababababab' eventTypes: *event-types createdAt: *created-at-schema example: id: '42' url: 'https://example.com/webhook' secret: 'abababababababababababababababababababababababababababababababab' eventTypes: [tweet.new, tweet.reply] createdAt: '2025-01-15T12:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '429': *rate-limit-exceeded-response /webhooks/telegram: post: operationId: createTelegramLink description: > Returns a t.me link to @XquikBot that connects a Telegram chat to the account's monitor events. Opening it & pressing Start connects the chat, which then gets each alert as a message. Alerts that wait together come as 1 digest. A busy chat gets 5 quick messages, then 1 every 30 s. Only 1 message a minute rings. The link works once, within 15 minutes. The chat appears in the webhook list with the URL `telegram:`, with deliveries, retries & resume as any webhook. In the chat, /stop pauses its alerts. It costs no credits. summary: Connect a Telegram chat tags: [Webhooks] security: *api-auth-2 requestBody: required: false description: The event types the chat gets. New posts (`tweet.new`) when omitted. Busy monitors send many replies & quotes, so name those only when the chat should get them. content: application/json: schema: type: object properties: eventTypes: *event-types example: eventTypes: [tweet.new, tweet.reply] responses: '201': description: Telegram link created content: application/json: schema: type: object required: [url, expiresAt] properties: url: type: string format: uri description: Opens @XquikBot with the link's code. example: 'https://t.me/XquikBot?start=Q2hhdExpbmtDb2RlRXhhbXBsZTAx' expiresAt: type: string format: date-time description: When the link stops working, 15 minutes after creation. example: '2025-01-15T12:15:00.000Z' example: url: 'https://t.me/XquikBot?start=Q2hhdExpbmtDb2RlRXhhbXBsZTAx' expiresAt: '2025-01-15T12:15:00.000Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '429': *rate-limit-exceeded-response '503': description: Telegram delivery is off for now. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'telegram_unavailable' message: 'Telegram alerts are off right now. Try again later.' /webhooks/{id}: patch: operationId: updateWebhook description: Updates an endpoint, event selection, or delivery settings. summary: Update webhook tags: [Webhooks] security: *api-auth-2 parameters: *resource-id-parameters requestBody: required: true description: Updated URL, event types, or active status. content: application/json: schema: type: object properties: url: type: string format: uri maxLength: 2048 example: 'https://example.com/webhook' eventTypes: *single-event-type isActive: *boolean-example-true example: url: 'https://example.com/webhook' eventTypes: - 'tweet.new' isActive: true responses: '200': description: Webhook updated content: application/json: schema: $ref: '#/components/schemas/Webhook' example: id: '42' url: 'https://example.com/webhook' eventTypes: [tweet.new] isActive: true consecutiveFailures: 0 deliveryStatus: active failureHardCap: 200 createdAt: '2025-01-15T12:00:00Z' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response delete: operationId: deleteWebhook description: Stops future deliveries to the selected webhook. summary: Deactivate webhook tags: [Webhooks] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': $ref: '#/components/responses/Success' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response /webhooks/{id}/deliveries: get: operationId: listWebhookDeliveries description: Returns delivery attempts and response outcomes, newest first. summary: List webhook deliveries tags: [Webhooks] security: *api-auth parameters: - $ref: '#/components/parameters/ResourceId' - $ref: '#/components/parameters/DeliveryLimit' - $ref: '#/components/parameters/After' responses: '200': description: Delivery list content: application/json: schema: type: object required: [deliveries, hasMore] properties: deliveries: type: array items: $ref: '#/components/schemas/Delivery' example: [] hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: deliveries: [] hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /webhooks/{id}/test: post: operationId: testWebhook description: Sends a signed test event to the configured endpoint. summary: Test webhook endpoint tags: [Webhooks] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': description: Test result content: application/json: schema: type: object required: [success, statusCode] properties: success: *boolean-example-true statusCode: type: integer minimum: 0 maximum: 599 example: 200 error: type: string example: '' example: success: true statusCode: 200 '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response /webhooks/{id}/resume: post: operationId: resumeWebhook description: Tests the endpoint before resuming a manually paused webhook. summary: Test and resume webhook endpoint tags: [Webhooks] security: *api-auth-2 parameters: *resource-id-parameters responses: '200': description: Webhook resumed after a successful test delivery content: application/json: schema: type: object required: [success, statusCode, webhook] properties: success: *boolean-example-true statusCode: type: integer minimum: 0 maximum: 599 example: 200 webhook: $ref: '#/components/schemas/Webhook' example: success: true statusCode: 200 webhook: id: '42' url: 'https://example.com/webhook' eventTypes: [tweet.new] isActive: true consecutiveFailures: 0 deliveryStatus: active failureHardCap: 200 createdAt: '2025-01-15T12:00:00Z' '400': description: Webhook test failed content: application/json: schema: type: object additionalProperties: false required: [error, statusCode, success] properties: error: type: string description: Delivery failure returned by the webhook sender. example: 'Connection timed out' statusCode: type: integer minimum: 0 maximum: 599 description: Webhook response status, or 0 before a response. example: 0 success: &boolean-false type: boolean const: false example: error: 'Connection timed out' statusCode: 0 success: false '401': $ref: '#/components/responses/Unauthenticated' '404': *not-found-response '429': *rate-limit-exceeded-response # ── X API (reads) ──────────────────────────────────────── /x/tweets: get: operationId: getBatchTweets description: Returns public tweet records for the requested IDs. summary: Get multiple tweets by IDs tags: - Tweets security: &read-auth [{ apiKey: [] }, { oauthBearer: [] }, {}] parameters: - name: ids in: query required: true schema: type: string maxLength: 13086 description: 1 to 100 posts, separated by commas. Each is a tweet ID or a tweet URL, such as x.com/nasa/status/20. Xquik reads a post named twice once. It skips any other entry & lists it under `skipped` with why. A batch without 1 post gets 400 `invalid_tweet_id`. A longer URL fails at the edge before Xquik reads it. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: >- Requested tweets in request order. After a partial read, Xquik reads the unresolved IDs once more. content: application/json: schema: allOf: - $ref: '#/components/schemas/PaginatedTweets' - type: object properties: skipped: type: array description: Each `ids` entry that names no post, with why. Absent when every entry names a post. items: type: object required: - entry - reason properties: entry: type: string description: The entry as sent. example: x.com/nasa reason: type: string description: Why the entry names no post. example: x.com/nasa is a profile, not a post. example: tweets: &example-launch-tweets - id: '1234567890' text: *launch-text createdAt: '2025-01-15T12:00:00Z' likeCount: 42 retweetCount: 5 replyCount: 3 quoteCount: 1 viewCount: 1500 bookmarkCount: 2 author: id: '9876543210' username: 'elonmusk' name: 'Elon Musk' verified: true has_next_page: false next_cursor: '' '400': *invalid-input-response '401': &anonymous-guest-authentication-response $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': *x-api-error-response post: operationId: createTweet description: Publishes a post through a connected X account. x-write-action: create_tweet summary: Create tweet tags: [X Write] security: *api-auth parameters: &write-idempotency-parameters - $ref: '#/components/parameters/WriteIdempotencyKey' requestBody: required: true description: Account and tweet content. Requires text, media, or both. content: application/json: schema: type: object required: [account] properties: account: type: string maxLength: 64 description: X account (@username or account ID) example: '@elonmusk' text: type: string maxLength: 100000 description: Tweet text (optional when media is provided) example: 'Just launched our new feature!' reply_to_tweet_id: type: string maxLength: 19 pattern: '^[1-9][0-9]{0,18}$' description: The post to reply to. Any X post ID works, from 1 to 19 digits. example: '1880000000000000000' community_id: type: string maxLength: 19 pattern: '^[1-9][0-9]{0,18}$' description: The Community to post into, from 1 to 19 digits. The account must be a member. Xquik picks the Community in X's composer, checks the post request names it & reads the post after. If X puts the post outside the Community, Xquik deletes it & charges nothing. It does not work with `reply_to_tweet_id`, since X keeps replies public. example: '1500000000000000000' is_note_tweet: *boolean-example-false media: type: array items: type: string maxLength: 2048 maxItems: 4 description: Publicly reachable URLs of up to 4 images or exactly 1 MP4 video up to 100 MB. Media adds 2 credits per started MB across all files. example: ['https://example.com/video.mp4'] examples: post: summary: 'A post with a video' value: account: '@elonmusk' text: 'Just launched our new feature!' media: - 'https://example.com/video.mp4' reply: summary: 'A reply' value: account: '@elonmusk' text: 'Thanks for the feedback!' reply_to_tweet_id: '1880000000000000000' community: summary: 'A post in a Community' value: account: '@elonmusk' text: 'Weekly build update.' community_id: '1500000000000000000' note: summary: 'A long post' value: account: '@elonmusk' is_note_tweet: true text: 'Release notes for this week. We rebuilt search, cut page load time in half, and fixed 40 reported bugs. Thank you to everyone who sent feedback.' responses: &media-write-responses '200': $ref: '#/components/responses/WriteActionCompleted' '202': $ref: '#/components/responses/WriteActionAccepted' '409': $ref: '#/components/responses/WriteIdempotencyConflict' '400': $ref: '#/components/responses/WriteInvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/AccountAuthError' '404': $ref: '#/components/responses/XAccountNotFound' '422': $ref: '#/components/responses/WriteRejected' '429': $ref: '#/components/responses/WriteRateLimited' '503': $ref: '#/components/responses/WriteTrackingUnavailable' '500': $ref: '#/components/responses/WriteError' '413': $ref: '#/components/responses/MediaTooLarge' '415': $ref: '#/components/responses/UnsupportedMedia' /x/write-actions/{id}: get: operationId: getWriteActionStatus description: Returns the current state of an asynchronous write action. summary: Get write action status tags: [X Write] security: *api-auth parameters: - name: id in: path required: true schema: type: string maxLength: 32 description: Write action ID returned by a pending write response. example: '12345' responses: '200': $ref: '#/components/responses/WriteActionCompleted' '202': $ref: '#/components/responses/WriteActionAccepted' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response /x/trends: get: operationId: getXTrends description: Returns X's current trends for a place you choose. Pick it by woeid, country or location name. Without one, trends are worldwide. Add at to read what was trending on Twitter at a past time, such as yesterday. Xquik keeps a Twitter trends archive from 2026-10-13 02:20 UTC on, with 1 list per place every 5 minutes. Each request costs 1 credit, however many trends it returns. summary: Get trending hashtags and topics from X by region, now or earlier tags: - Trends security: *read-auth x-payment-info: offers: - amount: '150' currency: &tempo-usd '0x20c000000000000000000000b9537d11c60e8b50' intent: charge method: tempo parameters: - name: woeid in: query schema: type: integer minimum: 1 default: 1 description: 'Region WOEID (1=Worldwide, 23424977=US, 23424975=UK, 23424969=Turkey). Wins over country & location.' - name: country in: query schema: type: string description: Country to read trends for, by name or 2-letter code, such as Turkey or TR. Case insensitive. - name: location in: query schema: type: string description: Town or country to read trends for, by name, such as Istanbul. Case insensitive. Add country when 2 towns share a name. /x/trends/locations lists every name. - name: count in: query description: Number of trending topics to return (1-50, default 30) schema: type: integer default: 30 minimum: 1 maximum: 50 - name: at in: query schema: type: string description: A past time, to read what was trending on Twitter then. Takes an ISO 8601 time, a date such as 2026-10-13, or Unix seconds. A time without a zone reads as UTC. It also takes a span back from now, as a number & s, m, h or d. So at=24h reads what was trending on Twitter yesterday at this hour, on every run of a schedule. The answer is the stored list nearest that time, with its own time in capturedAt. History starts 2026-10-13 02:20 UTC. A time over 24 hours from every stored list answers 400 at no charge. example: '2026-10-13T14:00:00Z' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of trending topics content: application/json: schema: type: object required: [trends, count, woeid] properties: trends: type: array items: type: object required: [name] properties: name: type: string example: '#AI' description: type: string example: 'Artificial intelligence discussions' query: type: string example: '%23AI' promotedContent: type: [string, 'null'] description: Promotion identifier from X. Null for organic trends. rank: &integer-example-one type: integer minimum: 1 example: 1 tweetVolume: type: [integer, 'null'] minimum: 0 description: Approximate public post volume when X supplies it. example: 250000 url: type: string format: uri description: X search URL for the trend. example: &trends-example - name: '#AI' description: 'Artificial intelligence discussions' promotedContent: null query: '%23AI' rank: 1 tweetVolume: 250000 url: 'https://x.com/search?q=%23AI' count: type: integer minimum: 0 example: 30 woeid: *integer-example-one location: type: object $ref: '#/components/schemas/TrendLocation' description: The place country or location named. Absent when woeid picked the place or the request named none. example: woeid: 2344116 name: 'Istanbul' country: 'Turkey' countryCode: 'TR' placeType: 'Town' placeTypeCode: 7 parentWoeid: 23424969 url: 'http://where.yahooapis.com/v1/place/2344116' capturedAt: type: string format: date-time description: When Xquik read this list from X. It comes from the stored list and is never estimated. example: '2026-10-13T14:00:26.000Z' requestedAt: type: string format: date-time description: The time the at parameter asked for, as Xquik read it. A span such as 24h shows here as the time it counted back to. Present only with at. example: '2026-10-13T14:00:00.000Z' '400': description: Unknown country or location, a time that does not read, or no stored list within 24 hours of at content: application/json: schema: *error-schema examples: unknownPlace: summary: X lists no such place value: error: 'invalid_input' message: 'X lists no trends for that place. List places with GET /x/trends/locations.' beforeHistory: summary: The time is before the first stored list value: error: 'invalid_input' message: 'Trends history for this place starts 2026-10-13 02:20 UTC. Ask for a later time.' noListNear: summary: No list is stored within 24 hours of the time value: error: 'invalid_input' message: 'No trends are stored within 24 hours of that time. The nearest list is from 2026-10-14 10:05 UTC.' '401': $ref: '#/components/responses/Unauthenticated' '402': $ref: '#/components/responses/PaymentRequired' '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': *x-api-error-response /x/trends/history: get: operationId: getXTrendsHistory description: Returns the Twitter trends archive of a place, as the lists X showed there over a range of time. Use it for trending on Twitter yesterday, last week or any day since 2026-10-13 02:20 UTC. Xquik stores 1 list per place every 5 minutes and keeps it for 25 months. Pick the place by woeid, country or location name, the range with from & to, and the step with every. from & to take a time or a span back from now, such as 7d, so a schedule can read the last day on every run. Each step returns the first list stored in it, with its own time. Each returned list costs 1 credit, so 24 lists cost 24 credits. A step with no stored list returns none and costs nothing. 1 request returns 24 lists, or up to 100 with limit. summary: Get the X (Twitter) trends archive of a place by date tags: - Trends security: *read-auth parameters: - name: woeid in: query schema: type: integer minimum: 1 default: 1 description: WOEID of the place, such as 1 for Worldwide or 23424969 for Turkey. It wins over country & location. /x/trends/locations lists every WOEID. - name: country in: query schema: type: string description: Country to read trends history for, by name or 2-letter code, such as Turkey or TR. Case insensitive. - name: location in: query schema: type: string description: Town or country to read trends history for, by name, such as Istanbul. Case insensitive. Add country when 2 towns share a name. /x/trends/locations lists every name. - name: from in: query schema: type: string description: Start of the range. Takes an ISO 8601 time, a date such as 2026-10-13, or Unix seconds. A time without a zone reads as UTC. It also takes a span back from now, as a number & s, m, h or d, so from=7d reads the last 7 days. Defaults to 24 hours before to. History starts 2026-10-13 02:20 UTC, and a range that begins earlier returns the stored part. Alias sinceTime. example: '2026-10-13' - name: to in: query schema: type: string description: End of the range, which it leaves out. Takes the forms of from, so from=2d with to=1d reads the day before the last 24 hours. Defaults to now. Alias untilTime. example: '2026-10-14' - name: every in: query schema: type: string default: 1h description: Step between 2 returned lists, as a number & m, h or d, such as 15m, 1h or 1d. A step under 5m returns every stored list. example: 1h - name: count in: query description: Trends to return in each list, from 1 to 50. schema: type: integer default: 30 minimum: 1 maximum: 50 - name: limit in: query schema: type: integer default: 24 minimum: 1 maximum: 100 description: Maximum lists 1 request returns & charges. A wider range gives a next_cursor for the next lists. A low credit balance can return fewer. - name: cursor in: query schema: type: string maxLength: 4096 description: The next_cursor of the page before, for the next lists. It keeps the time of the first request, so a range of spans stays the same on every page. example: '2026-10-14T00:00:00.000Z~1791979200000' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Stored trend lists of the place, oldest first content: application/json: schema: type: object required: - snapshots - count - fromTime - toTime - woeid - has_next_page - next_cursor properties: fromTime: type: string format: date-time description: Start of the range as Xquik read it. A span such as 7d shows here as the time it counted back to. example: '2026-10-13T00:00:00.000Z' toTime: type: string format: date-time description: End of the range as Xquik read it, which the range leaves out. Without to, it is the time of the first request. example: '2026-10-14T00:00:00.000Z' snapshots: type: array description: 1 stored list per step, oldest first. A step with no stored list is left out. items: type: object required: [capturedAt, count, trends] properties: capturedAt: type: string format: date-time description: When Xquik read this stored list from X. Xquik never estimates it. example: '2026-10-13T14:00:26.000Z' count: type: integer minimum: 0 description: Trends in this list. example: 1 trends: type: array items: type: object required: [name] properties: name: type: string example: '#AI' description: type: string example: 'Artificial intelligence discussions' query: type: string example: '%23AI' promotedContent: type: [string, 'null'] description: X's promotion ID of a promoted trend. Null for the others. rank: type: integer minimum: 1 description: The trend's place in X's list at that time. example: 1 tweetVolume: type: [integer, 'null'] minimum: 0 description: X's post count for the trend at that time, when X showed one. example: 250000 url: type: string format: uri description: The trend's search link on X. example: *trends-example example: - capturedAt: '2026-10-13T14:00:26.000Z' count: 1 trends: *trends-example count: type: integer minimum: 0 description: Lists returned & charged. example: 1 woeid: *integer-example-one location: type: object $ref: '#/components/schemas/TrendLocation' description: The place the request named by country or location. Absent when it sent a woeid or named no place. example: woeid: 23424969 name: 'Turkey' country: 'Turkey' countryCode: 'TR' placeType: 'Country' placeTypeCode: 12 parentWoeid: 1 url: 'http://where.yahooapis.com/v1/place/23424969' has_next_page: type: boolean description: Whether the range holds more lists. example: false next_cursor: type: string description: Send it as cursor for the next lists. Empty on the last page. example: '' example: fromTime: '2026-10-13T00:00:00.000Z' toTime: '2026-10-14T00:00:00.000Z' snapshots: - capturedAt: '2026-10-13T14:00:26.000Z' count: 1 trends: *trends-example count: 1 woeid: 1 has_next_page: false next_cursor: '' '400': description: Unknown country or location, a time or step that does not read, a range that ends before the first stored list, or a value past its maxLength content: application/json: schema: *error-schema example: error: 'invalid_input' message: 'Trends history for this place starts 2026-10-13 02:20 UTC. Ask for a later time.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': *x-api-error-response /x/trends/locations: get: operationId: getXTrendLocations description: Returns the places X offers trends for. Pass a location's woeid to /x/trends. Each returned location costs 1 credit. summary: List the locations X offers trends for tags: - Trends security: *read-auth parameters: - name: country in: query schema: type: string description: Country name or 2-letter code, such as Turkey or TR. Case insensitive. Returns the country & its towns. - name: placeType in: query schema: type: string enum: [country, town, worldwide, unknown] description: Kind of place. Case insensitive. X labels a few towns unknown. - name: q in: query schema: type: string description: Text the location name contains, such as york. Case insensitive. Alias query. - name: limit in: query schema: type: integer minimum: 1 description: Maximum locations to return. Omit it for every match. A low credit balance can return fewer. Aliases pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Locations X offers trends for content: application/json: schema: type: object required: [locations, count, total] properties: locations: type: array items: $ref: '#/components/schemas/TrendLocation' example: - woeid: 2344116 name: 'Istanbul' country: 'Turkey' countryCode: 'TR' placeType: 'Town' placeTypeCode: 7 parentWoeid: 23424969 url: 'http://where.yahooapis.com/v1/place/2344116' count: type: integer minimum: 0 description: Locations returned & charged. example: 1 total: type: integer minimum: 0 description: Locations that match the filters, before limit. example: 1 message: type: string description: What to send instead. Present only when no location matches. example: Unknown placeType. Use country, town, worldwide or unknown. '400': $ref: '#/components/responses/UnknownField' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': *x-api-error-response /x/news/{id}/versions: get: operationId: getXNewsStoryVersions summary: Get every version of an X news story, oldest first description: Returns each version X wrote of 1 news story, the AI trends x.com shows under Explore & News. Each version has its time, headline & text, oldest first, so you can see how the story changed. X lists every version at once. Each request costs 1 credit. tags: - Trends security: *read-auth parameters: - name: id in: path required: true schema: { type: string, maxLength: 2048 } description: X news story ID, or the URL-encoded story link, such as x.com/i/trending/2110209733533598095. example: '2110209733533598095' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: The story's versions, oldest first content: application/json: schema: type: object required: [id, count, versions] properties: id: type: string description: The story's ID, as the request named it. example: '2110209733533598095' count: type: integer minimum: 1 description: Versions returned. example: 1 versions: type: array items: $ref: '#/components/schemas/NewsVersion' example: - id: '2110211669641105725' createdAt: '2026-10-14T03:30:42.536Z' headline: "Elon Musk Pushes Starlink for India's Remote Areas Amid Regulatory Hurdles" text: "Musk has accused Reliance Industries' Mukesh Ambani of blocking Starlink's entry to protect local telecom giants like Jio, while India's government insists on equal treatment for all applicants, including ongoing security reviews. In Vietnam, Starlink already provides free internet to isolated spots for tourism and disaster response, highlighting its potential for hard-to-reach areas. Yet challengers note India's cheap mobile data from Jio and Airtel covers most needs, raising questions on pricing and national security as Starlink seeks final clearances." example: id: '2110209733533598095' count: 1 versions: - id: '2110211669641105725' createdAt: '2026-10-14T03:30:42.536Z' headline: "Elon Musk Pushes Starlink for India's Remote Areas Amid Regulatory Hurdles" text: "Musk has accused Reliance Industries' Mukesh Ambani of blocking Starlink's entry to protect local telecom giants like Jio, while India's government insists on equal treatment for all applicants, including ongoing security reviews. In Vietnam, Starlink already provides free internet to isolated spots for tourism and disaster response, highlighting its potential for hard-to-reach areas. Yet challengers note India's cheap mobile data from Jio and Airtel covers most needs, raising questions on pricing and national security as Starlink seeks final clearances." '400': description: The path names no story or runs past its maxLength. Free. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'invalid_news_id' message: 'Send a story ID or link, such as x.com/i/trending/2110209733533598095.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': description: No story holds the ID. Free. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'news_not_found' message: 'Story not found. Copy its ID from its x.com/i/trending link.' '424': *x-api-error-response '429': *rate-limit-exceeded-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' /x/hashflags: get: operationId: getXHashflags description: Returns X's hashflags, the custom emoji X shows after some hashtags. Lists the ones running now unless activeOnly is false. Each returned hashflag costs 1 credit. summary: List the hashflags X shows after hashtags tags: - Trends security: *read-auth parameters: - name: q in: query schema: type: string description: Text the hashtag contains, such as football. Case insensitive. A leading hash sign is ignored. Alias query. - name: activeOnly in: query schema: type: boolean default: true description: Keeps hashflags that run now. Send false to add ended & upcoming ones. - name: limit in: query schema: type: integer minimum: 1 description: Maximum hashflags to return. Omit it for every match. A low credit balance can return fewer. Aliases pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Hashflags X shows after hashtags content: application/json: schema: type: object required: [hashflags, count, total] properties: hashflags: type: array items: $ref: '#/components/schemas/Hashflag' example: - hashtag: 'AION2' assetUrl: 'https://abs.twimg.com/hashflags/BF-16692_AIon2_jp_Hashmoji_v3/BF-16692_AIon2_jp_Hashmoji_v3.png' startsAt: '2026-10-02T10:00:00.000Z' endsAt: '2027-01-03T14:59:00.000Z' isHashfettiEnabled: false animations: [] count: type: integer minimum: 0 description: Hashflags returned & charged. example: 1 total: type: integer minimum: 0 description: Hashflags that match the filters, before limit. example: 1 message: type: string description: What to send instead. Present only when no hashflag matches. example: No hashflag runs now. Send activeOnly=false to list the rest. '400': $ref: '#/components/responses/UnknownField' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': { $ref: '#/components/responses/XApiError' } /x/places/search: get: operationId: searchXPlaces description: Finds places on X by name. Pass a place's id as place to /x/tweets/search to read posts tagged there. X ranks the places, so their order can differ between requests. Each returned place costs 1 credit. summary: Search X places by name tags: - Tweets security: *read-auth parameters: - name: q in: query required: true schema: type: string description: Place name to search for, such as istanbul. Alias query. - name: limit in: query schema: type: integer minimum: 1 description: Maximum places to return. Omit it for every place X finds. A low credit balance can return fewer. Aliases pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Places X found for the name content: application/json: schema: type: object required: [places, count, total] properties: places: type: array items: $ref: '#/components/schemas/PlaceSearchResult' example: - id: '5e02a0f0d91c76d2' name: 'İstanbul' fullName: 'İstanbul, Türkiye' country: 'Turkey' countryCode: 'TR' placeType: 'city' url: 'https://api.twitter.com/1.1/geo/id/5e02a0f0d91c76d2.json' centroid: [28.84318392941324, 41.054196399999995] boundingBox: type: 'Polygon' coordinates: - - [28.6321043, 40.8027337] - [28.6321043, 41.2399073] - [29.3783413, 41.2399073] - [29.3783413, 40.8027337] attributes: {} containedWithin: [] count: type: integer minimum: 0 description: Places returned & charged. example: 1 total: type: integer minimum: 0 description: Places X found, before limit. example: 1 message: type: string description: What to send instead. Present only when X finds no place. example: X found no place for that text. Try a city or country name. '400': description: Missing place search text content: application/json: schema: *error-schema example: error: 'missing_query' message: 'Search query required. Use q.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response '424': { $ref: '#/components/responses/XApiError' } /x/tweets/search: get: operationId: searchTweets summary: Search tweets with minLikes, normalized likeCount, media & cursors x-mcp-summary: Search tweets with minLikes, normalized like_count, media & cursors description: Tweets include authors, like counts, media, URLs & cursors. Omit mode for maximum coverage. Reuse next_cursor with unchanged filters. tags: - Tweets security: *read-auth parameters: - name: q in: query required: true schema: type: string maxLength: 4096 description: Query, Tweet ID, or URL. Alias query. Hyphens negate terms. Use exactPhrase for literals. `from:` & `-from:` take a handle or a user ID, also in an OR group. Valid bounds apply per page. `since:` & `until:` dates are UTC days, written YYYY-MM-DD. 25/12/2026 & 12/25/2026 also work, since each has 1 reading. 04/01/2026 has 2 & answers 424 with the form to write. `since_time:` & `until_time:` take Unix seconds or an ISO 8601 time. `list:` takes a public List's ID. A private List answers 404 list_not_found. X searches up to 512 characters. A longer query answers 424 before any read, unless a term of its first OR group fits alone. When each OR alternative has `-filter:replies`, Xquik drops every reply X sends. Dropped replies cost nothing. - name: queryType in: query required: false schema: type: string maxLength: 32 default: Latest description: Latest lists posts newest first. Top keeps X's engagement ranking within each read. Xquik reads several of X's views, so a later page can hold a post X ranks higher. Top skips posts X shows above a ranked reply that cannot match the query. They cost nothing. Any case works. Photos, Videos & Media read Latest with mediaType images, videos or media, unless mediaType is set. People & Lists answer 400 & point to /x/users/search & /x/lists/search. Aliases result_type, sort_order, type, search_type, product, category & section. - $ref: '#/components/parameters/AutomaticCoverageMode' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - name: limit in: query required: false schema: &bounded-result-limit type: integer minimum: 1 maximum: 10000 description: > Most unique matches to return after filtering. Default 20. Explicit coverage defaults to 2000. At the deadline it returns kept rows & diagnostics. Xquik bills only returned rows. A low credit balance can cut results. A balance that covers 0 rows returns 402. Its aliases are pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - name: sinceDate in: query schema: type: string format: date maxLength: 64 description: Start date as a UTC day, written YYYY-MM-DD. 25/12/2026 & 12/25/2026 also work, since each has 1 reading. A date that fits both orders reads month first, so 04/01/2026 is 1 April. - name: untilDate in: query schema: type: string format: date maxLength: 64 description: End date as a UTC day, inclusive, so its own posts count. It takes the same date forms as sinceDate. - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/CardName' - $ref: '#/components/parameters/Source' - $ref: '#/components/parameters/ExcludeSource' - $ref: '#/components/parameters/Geocode' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/Near' - $ref: '#/components/parameters/Within' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/Safe' - $ref: '#/components/parameters/News' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/SearchReplies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Keywords' - $ref: '#/components/parameters/ListId' - $ref: '#/components/parameters/Place' - $ref: '#/components/parameters/PlaceCountry' - $ref: '#/components/parameters/PointRadius' - $ref: '#/components/parameters/BoundingBox' - $ref: '#/components/parameters/AdvancedQuery' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Search results content: application/json: schema: oneOf: - $ref: '#/components/schemas/PaginatedTweets' - $ref: '#/components/schemas/TweetSearchCoverageResponse' example: tweets: *example-launch-tweets has_next_page: true next_cursor: 'DAACCgACGRElMJcAAA' '400': description: Missing query content: application/json: schema: *error-schema example: error: 'missing_query' message: 'Search query required. Use q.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': $ref: '#/components/responses/NotFound' description: A missing user returns user_not_found. A missing tweet returns tweet_not_found. '502': *x-api-error-response '429': &rate-limit-exceeded-response-2 $ref: '#/components/responses/RateLimitExceeded' '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/tweets/top: get: operationId: getTopTweets summary: List the top tweets on X by likes, replies or views description: > Returns the tweets X ranks highest by 1 metric over the last day, week or month, as x.com's Inspiration page shows them. Covers all of X unless you pick a country or a language. Pages hold up to 20 tweets, and the list ends at 100. Each tweet costs 1 credit. tags: - Tweets security: *read-auth parameters: - name: metric in: query description: > What to rank tweets by. Defaults to likes. Singular names work too, such as like. schema: type: string enum: [likes, replies, quotes, bookmarks, shares, views] default: likes example: likes - name: window in: query description: > How far back to look. Defaults to day. Also takes 24h, 7d, 30d, daily, weekly and monthly. schema: type: string enum: [day, week, month] default: day example: day - name: country in: query description: > Only tweets from 1 country, as a 2- or 3-letter ISO 3166 code, such as US or USA. Send country or language, not both. schema: type: string maxLength: 16 example: US - name: language in: query description: > Only tweets in 1 language, as a 2-letter code, such as en. Send country or language, not both. schema: type: string maxLength: 16 example: en - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Top tweets content: application/json: schema: $ref: '#/components/schemas/PaginatedTweets' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/articles/{tweetId}: get: operationId: getArticle summary: Get full X Article content with cover image and metadata description: Returns the full content of an X Article (long-form post) by numeric tweet ID. Returns article_not_found when the tweet is valid but is not an X Article. tags: - Articles security: *read-auth x-payment-info: offers: - amount: '750' currency: *tempo-usd intent: charge method: tempo parameters: - name: tweetId in: path required: true schema: type: string maxLength: 2048 description: Tweet ID of the article, 15-19 digits, or its URL-encoded tweet URL, such as x.com/nasa/status/2102882545427714266. example: '2102882545427714266' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Article with author content: application/json: schema: type: object required: [article] properties: article: type: object properties: articleId: type: string description: X's ID for the Article, which differs from its post's ID example: '2100651802404544512' title: type: string example: 'The Future of AI' previewText: type: string example: 'A deep dive into the latest AI trends...' summaryText: type: string description: X's summary of the Article, when X has one example: '- Pinned DMs now work on desktop.' coverImageUrl: type: string example: 'https://pbs.twimg.com/media/example.jpg' coverMedia: $ref: '#/components/schemas/PublicMetadata' metadata: $ref: '#/components/schemas/PublicMetadata' lifecycleState: $ref: '#/components/schemas/PublicMetadata' bodyText: type: string description: Plain text joined from all article blocks example: 'This is the first paragraph of the article.' bodyMarkdown: type: string description: Article blocks as Markdown, with headings, lists, bold, italic, links, images & embedded posts as their x.com URLs. Holds no HTML. example: "## Pinned DMs\n\n**Pinning DMs** now works on [desktop](https://x.com/discord)." contents: type: array items: type: object properties: type: type: string description: 'Block type, which is paragraph, header-one, header-two, header-three, header-four, header-five, header-six, unordered-list-item, ordered-list-item, blockquote, code-block, markdown, media, tweet or divider.' example: 'paragraph' tweetId: type: string description: ID of the post a tweet block embeds example: '2058951429612875794' links: type: array description: Links in the block's text, with the text range each covers items: type: object properties: offset: type: integer minimum: 0 example: 15 length: type: integer minimum: 0 example: 13 url: type: string example: 'https://x.com/discord' text: type: string example: 'This is the first paragraph of the article.' url: type: string description: Image URL of an image block. A video or GIF block lists its files in `variants`. example: 'https://pbs.twimg.com/media/example.jpg' previewUrl: type: string description: Image of a media block, or the preview image of a video or GIF example: 'https://pbs.twimg.com/media/example.jpg' width: type: integer minimum: 0 description: Width of the image or preview image example: 1200 height: type: integer minimum: 0 description: Height of the image or preview image example: 675 mediaType: type: string enum: [image, video, gif] description: What a media block holds example: video caption: type: string description: Caption the author wrote under a media block example: 'Wordle is excellent because of its simplicity' altText: type: string description: Alt text of the image or preview image example: 'A chart of daily active users' durationMs: type: integer minimum: 0 description: Length of a video, in milliseconds example: 42376 variants: type: array description: Files of a video or GIF block, in X's order items: type: object required: [contentType, url] properties: bitrate: type: integer minimum: 0 example: 832000 contentType: type: string example: video/mp4 url: type: string example: 'https://video.twimg.com/ext_tw_video/1765989573685837824/pu/vid/avc1/462x360/RbrgrAMdncI-EzW7.mp4?tag=12' inlineStyleRanges: type: array description: Inline text formatting ranges items: type: object properties: offset: type: integer minimum: 0 example: 0 length: type: integer minimum: 0 example: 8 style: type: string description: X's name for the style, such as Bold or Italic example: 'Bold' createdAt: ×tamp-text-example-schema type: string example: '2025-01-15T12:00:00Z' likeCount: type: integer minimum: 0 example: 150 replyCount: type: integer minimum: 0 example: 23 quoteCount: type: integer minimum: 0 example: 8 retweetCount: type: integer minimum: 0 description: Reposts of the Article's post. 0 or more. example: 105 bookmarkCount: type: integer minimum: 0 description: Accounts that bookmarked the Article's post. 0 or more. example: 423 viewCount: type: integer minimum: 0 example: 5000 author: $ref: '#/components/schemas/ArticleAuthor' example: article: articleId: '2100651802404544512' title: 'The Future of AI' previewText: 'A deep dive into the latest AI trends...' coverImageUrl: 'https://pbs.twimg.com/media/example.jpg' contents: - type: 'paragraph' text: 'This is the first paragraph of the article.' links: - offset: 18 length: 9 url: 'https://example.com/paragraph' - type: 'tweet' tweetId: '2058951429612875794' createdAt: '2025-01-15T12:00:00Z' metadata: first_published_at_secs: 1736942400 lifecycleState: modified_at_secs: 1736946000 likeCount: 150 replyCount: 23 quoteCount: 8 retweetCount: 40 bookmarkCount: 61 viewCount: 5000 author: id: '9876543210' name: 'Elon Musk' username: 'elonmusk' profilePicture: 'https://pbs.twimg.com/profile_images/example.jpg' '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': description: Article not found content: application/json: schema: *error-schema example: error: 'article_not_found' message: 'Article not found. Use an X Article tweet ID.' '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}: get: operationId: lookupTweet description: Returns 1 public tweet with author, metrics, and media. summary: Get tweet with full text, author, metrics and media tags: - Tweets security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Tweet with author content: application/json: schema: type: object required: [tweet] properties: tweet: $ref: '#/components/schemas/TweetDetail' author: type: object $ref: '#/components/schemas/TweetAuthor' example: id: '9876543210' username: 'elonmusk' name: 'Elon Musk' followers: 150000000 verified: true example: tweet: id: '1234567890' text: 'New feature' retweetCount: 5 replyCount: 3 likeCount: 42 quoteCount: 1 viewCount: 1500 bookmarkCount: 2 '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': &tweet-not-found-response $ref: '#/components/responses/TweetNotFound' '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response delete: operationId: deleteTweet description: Deletes an authored post through a connected X account. x-write-action: delete_tweet summary: Delete tweet tags: [X Write] security: *api-auth parameters: &tweet-write-parameters - $ref: '#/components/parameters/WriteIdempotencyKey' - $ref: '#/components/parameters/TweetPathId' requestBody: required: true description: Account that owns the tweet. content: &x-account-body-content-with-example application/json: schema: $ref: '#/components/schemas/XAccountBody' example: account: '@elonmusk' responses: &x-rate-limited-write-responses '200': { $ref: '#/components/responses/WriteActionCompleted' } '202': { $ref: '#/components/responses/WriteActionAccepted' } '409': { $ref: '#/components/responses/WriteIdempotencyConflict' } '400': { $ref: '#/components/responses/WriteInvalidInput' } '401': { $ref: '#/components/responses/Unauthenticated' } '402': { $ref: '#/components/responses/PaymentRequired' } '403': { $ref: '#/components/responses/AccountAuthError' } '404': { $ref: '#/components/responses/XAccountNotFound' } '422': { $ref: '#/components/responses/WriteRejected' } '429': $ref: '#/components/responses/RateLimitedByX' '503': { $ref: '#/components/responses/WriteTrackingUnavailable' } '500': { $ref: '#/components/responses/WriteError' } /x/tweets/{id}/like: post: operationId: likeTweet description: Likes a post through a connected X account. x-write-action: like summary: Like tweet tags: [X Write] security: *api-auth parameters: *tweet-write-parameters requestBody: required: true description: Account to perform the like. content: *x-account-body-content-with-example responses: *x-rate-limited-write-responses delete: operationId: unlikeTweet description: Removes a like through a connected X account. x-write-action: unlike summary: Unlike tweet tags: [X Write] security: *api-auth parameters: *tweet-write-parameters requestBody: required: true description: Account that liked the tweet. content: &x-account-body-content application/json: schema: $ref: '#/components/schemas/XAccountBody' example: account: '@elonmusk' responses: *x-rate-limited-write-responses /x/tweets/{id}/retweet: post: operationId: retweet description: Reposts a tweet through a connected X account. x-write-action: retweet summary: Retweet tags: [X Write] security: *api-auth parameters: *tweet-write-parameters requestBody: required: true description: Account to perform the retweet. content: *x-account-body-content responses: *x-rate-limited-write-responses delete: operationId: unretweet description: Removes a repost through a connected X account. x-write-action: unretweet summary: Unretweet tags: [X Write] security: *api-auth parameters: *tweet-write-parameters requestBody: required: true description: Account that retweeted the tweet. content: *x-account-body-content responses: *x-rate-limited-write-responses /x/users/batch: get: operationId: getBatchUsers description: Returns public profiles for up to 100 user IDs, usernames or profile links. Send ids or usernames, not both. Each returned profile costs 1 credit. summary: Look up multiple users by IDs or usernames in 1 call tags: - Users security: *read-auth parameters: - name: ids in: query schema: type: string maxLength: 13081 description: Comma-separated numeric user IDs (1-100 values). Xquik ignores duplicate IDs and keeps the first-seen order. A longer URL fails at the edge before Xquik reads it. - name: usernames in: query schema: type: string maxLength: 13075 example: 'nasa,@OpenAI,x.com/verge' description: Comma-separated X usernames, with or without @, or profile links such as x.com/nasa (1-100 values), in place of ids. A name in another case is the same account. A longer URL fails at the edge before Xquik reads it. - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Matched users plus reconciliation metadata. content: application/json: schema: $ref: '#/components/schemas/BatchUsers' example: users: - id: '9876543210' username: 'elonmusk' name: 'Elon Musk' has_next_page: false next_cursor: '' requested_count: 2 processed_count: 2 returned_count: 1 unavailable_ids: ['1234567890'] failed_ids: [] unprocessed_ids: [] '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/batch/tweets: get: operationId: getBatchUserTweets description: Returns the newest posts of up to 20 users, named by user ID, username or profile link, in the order named. Send ids or usernames, not both. Each post costs 1 credit. A user in unavailable_ids or unprocessed_ids costs nothing. summary: List the newest tweets of multiple users in 1 call tags: - Users security: *read-auth parameters: - name: ids in: query schema: type: string maxLength: 13074 description: Comma-separated numeric user IDs (1-20 values). Xquik ignores duplicate IDs and keeps the first-seen order. A longer URL fails at the edge before Xquik reads it. - name: usernames in: query schema: type: string maxLength: 13068 example: 'nasa,@OpenAI,x.com/verge' description: Comma-separated X usernames, with or without @, or profile links such as x.com/nasa (1-20 values), in place of ids. A name in another case is the same account. A number is a user ID. A longer URL fails at the edge before Xquik reads it. - name: pageSize in: query description: > Posts per user (1-20, default 20). A low credit balance can return fewer. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 20 default: 20 - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Each user's newest posts, plus the users not read. content: application/json: schema: $ref: '#/components/schemas/BatchUserTweets' example: tweets: *example-launch-tweets has_next_page: false next_cursor: '' unavailable_ids: ['1234567890'] unprocessed_ids: [] '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/search: get: operationId: searchUsers description: Returns public profiles matching a name or username. summary: Search users by name or username tags: - Users security: *read-auth parameters: - name: q in: query required: true schema: type: string description: User search query - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/EnrichProfiles' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: User search results headers: &user-list-headers X-Xquik-Profile-Enrichment: $ref: '#/components/headers/ProfileEnrichment' X-Xquik-Credits-Charged: $ref: '#/components/headers/CreditsCharged' content: &paginated-users-content application/json: schema: $ref: '#/components/schemas/PaginatedUsers' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/search/autocomplete: get: operationId: autocompleteSearch description: Returns the accounts, topics, hashtags & cashtags X suggests while someone types a search. X may rank them differently per request. Costs 1 credit per suggestion. summary: Get search suggestions for a partial query tags: - Users security: *read-auth parameters: - name: q in: query required: true schema: type: string minLength: 1 example: nasa description: > Text typed so far. Start with # for hashtags or $ for cashtags. A # query returns hashtags & the accounts X suggests for it. Its alias is query. - name: types in: query schema: type: string default: users,topics,hashtags,cashtags example: users,topics description: > Comma-separated suggestion types from users, topics, hashtags & cashtags. Omit for all. With only hashtags or only cashtags, the query gets its # or $ when it lacks one. - name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 20 description: > Most suggestions to return, from 1 to 100. Default 20. Accounts fill it first, then topics, hashtags & cashtags. A low credit balance can return fewer. Its aliases are pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Search suggestions content: application/json: schema: $ref: '#/components/schemas/SearchSuggestions' '400': description: Missing query or unknown type content: application/json: schema: *error-schema examples: missingQuery: summary: No query value: error: 'missing_query' message: 'Search query required. Use q.' unknownType: summary: Unknown type value: error: 'invalid_params' message: 'Send types as users, topics, hashtags or cashtags, separated by commas.' parameter: 'types' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}: get: operationId: getUser description: Returns 1 public profile with counts and verification details. summary: Get user profile with follower counts and verification tags: - Users security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: User profile content: application/json: schema: $ref: '#/components/schemas/UserProfile' example: id: '9876543210' username: elonmusk name: Elon Musk description: CEO of Tesla, SpaceX, and X followers: 150000000 following: 500 verified: true '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/follow: post: operationId: followUser description: Follows a user through a connected X account. x-write-action: follow summary: Follow user tags: [X Write] security: *api-auth parameters: &user-write-parameters - $ref: '#/components/parameters/WriteIdempotencyKey' - $ref: '#/components/parameters/UserPathId' requestBody: required: true description: Account to perform the follow. content: *x-account-body-content responses: &write-responses '200': $ref: '#/components/responses/WriteActionCompleted' '202': $ref: '#/components/responses/WriteActionAccepted' '409': $ref: '#/components/responses/WriteIdempotencyConflict' '400': $ref: '#/components/responses/WriteInvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/AccountAuthError' '404': $ref: '#/components/responses/XAccountNotFound' '422': $ref: '#/components/responses/WriteRejected' '429': $ref: '#/components/responses/WriteRateLimited' '503': $ref: '#/components/responses/WriteTrackingUnavailable' '500': $ref: '#/components/responses/WriteError' delete: operationId: unfollowUser description: Unfollows a user through a connected X account. x-write-action: unfollow summary: Unfollow user tags: [X Write] security: *api-auth parameters: *user-write-parameters requestBody: required: true description: Account that follows the target user. content: *x-account-body-content responses: *write-responses /x/users/{id}/remove-follower: post: operationId: removeFollower description: Removes a follower from a connected X account. x-write-action: remove_follower summary: Remove follower tags: [X Write] security: *api-auth parameters: *user-write-parameters requestBody: required: true description: Connected account to remove the follower from. content: *x-account-body-content responses: *write-responses /x/followers/check: get: operationId: checkFollow description: Returns whether 1 public account follows another, & the reverse, with each account's username & user ID as X names them. summary: Check if a user follows another tags: - Users security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - name: source in: query required: true schema: type: string maxLength: 2048 description: Source user ID, username, @username, or X or Twitter profile URL, such as x.com/i/user/11348282. A number is a user ID. - name: target in: query required: true schema: type: string maxLength: 2048 description: Target user ID, username, @username, or X or Twitter profile URL, such as x.com/i/user/11348282. A number is a user ID. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Follow check result content: application/json: schema: type: object required: [isFollowing, isFollowedBy, sourceUsername, targetUsername] properties: isFollowing: *boolean-example-true isFollowedBy: *boolean-example-false sourceId: type: string description: The source account's user ID, as X gives it. example: '11348282' sourceUsername: &username-example-schema type: string example: 'elonmusk' targetId: type: string description: The target account's user ID, as X gives it. example: '34743251' targetUsername: type: string description: The target account's username, in lower case. example: 'spacex' example: isFollowing: false isFollowedBy: true sourceId: '11348282' sourceUsername: 'nasa' targetId: '34743251' targetUsername: 'spacex' '400': description: Missing or invalid params, or a value past its maxLength content: application/json: schema: *error-schema example: error: 'missing_params' '401': *unauthenticated-response '402': *payment-required-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/dm/{userId}: post: operationId: sendDm description: > Sends a direct message through a connected X account. Once X rate limits an account's DMs, its DMs get 429 until X's reset. Xquik sends nothing to X & charges nothing. `Retry-After` & `nextAction.afterMs` give the wait. x-write-action: send_dm summary: Send direct message tags: [X Write] security: *api-auth parameters: - $ref: '#/components/parameters/WriteIdempotencyKey' - $ref: '#/components/parameters/DmUserPathId' requestBody: required: true description: Account, message text, and an optional media attachment. content: application/json: schema: type: object required: [account, text] properties: account: type: string maxLength: 64 description: X account (@username or ID) sending the DM example: '@elonmusk' text: type: string maxLength: 40000 example: 'Example text' media_ids: type: array minItems: 1 maxItems: 1 items: type: string maxLength: 19 description: Optional array containing exactly 1 uploaded media ID. example: ['1234567890123456789'] example: account: '@elonmusk' text: 'Example text content' media_ids: ['1234567890123456789'] responses: *write-responses /x/dm/{userId}/messages/{messageId}: delete: operationId: deleteDm description: > Deletes 1 DM from the account's side. The other person keeps it. Success means the account's conversation no longer shows it. A DM still shown gets 422 `x_dm_not_deleted`, and Xquik charges nothing. x-write-action: delete_dm summary: Delete direct message tags: [X Write] security: *api-auth parameters: - $ref: '#/components/parameters/WriteIdempotencyKey' - $ref: '#/components/parameters/DmUserPathId' - $ref: '#/components/parameters/DmMessagePathId' - name: account in: query required: true schema: { type: string, maxLength: 64 } description: Connected X account (@username or ID) that sees the DM. responses: *write-responses /x/media: post: operationId: uploadMedia description: Uploads media and returns an identifier for later writes. x-write-action: upload_media summary: Upload media tags: [X Write] security: *api-auth parameters: *write-idempotency-parameters requestBody: required: true description: Send the file as multipart form data, or a JSON URL for Xquik to download. content: multipart/form-data: schema: type: object required: [account, file] properties: account: type: string maxLength: 64 description: X account (@username or ID) uploading media example: '@elonmusk' file: type: string maxLength: 15728640 format: binary description: Media file to upload, up to 15 MB. A larger file gets 413 `media_too_large` before any account lookup. example: 'binary-content' is_long_video: type: boolean description: Set true only for video/mp4 multipart uploads longer than 140 seconds. example: false example: account: '@elonmusk' file: 'file_value' is_long_video: true application/json: schema: type: object required: [account, url] properties: account: type: string maxLength: 64 description: X account (@username or ID) uploading media from URL example: '@elonmusk' url: type: string maxLength: 2048 format: uri pattern: '^https://' description: HTTPS URL to download and upload as media, up to 15 MB. Another scheme gets 400 `invalid_media_url`. example: 'https://example.com/image.png' example: account: '@elonmusk' url: 'https://example.com/image.png' responses: *media-write-responses /x/media/download: post: operationId: downloadMedia description: Downloads images and videos attached to selected tweets. summary: Download images and videos from tweets tags: - Media security: *api-auth requestBody: required: true description: 1 tweet URL or ID under any accepted alias. For a bulk download, send up to 50 tweet URLs or IDs as an array. A non-empty `tweetIds` uses bulk mode. content: application/json: schema: type: object properties: tweetInput: type: string maxLength: 2048 description: Tweet URL or ID (single tweet) example: 'https://x.com/elonmusk/status/1234567890' tweetId: type: string maxLength: 2048 description: Numeric tweet ID alias for tweetInput example: '1234567890' tweetUrl: type: string maxLength: 2048 description: Tweet URL alias for tweetInput example: 'https://x.com/elonmusk/status/1234567890' tweetIds: type: array items: type: string maxLength: 2048 maxItems: 50 description: Up to 50 tweet URLs or IDs. An item that names no post gets 400 `invalid_tweet_id`, which says which item. example: ['1234567890', '1234567891'] examples: url: summary: '1 post by URL' value: tweetInput: 'https://x.com/elonmusk/status/1234567890' id: summary: '1 post by ID' value: tweetId: '1234567890' urlAlias: summary: '1 post by URL alias' value: tweetUrl: 'https://x.com/elonmusk/status/1234567890' bulk: summary: 'Up to 50 posts' value: tweetIds: - '1234567890' - 'https://x.com/elonmusk/status/1234567891' responses: '200': description: 'Media download result. A single download returns tweetId, galleryUrl & cacheHit. A bulk download returns galleryUrl, totalTweets & totalMedia.' content: application/json: schema: type: object properties: tweetId: *tweet-id-example-schema galleryUrl: type: string example: 'https://xquik.com/gallery/abc123' cacheHit: *boolean-example-false totalTweets: type: integer minimum: 0 example: 2 totalMedia: type: integer minimum: 0 example: 5 example: tweetId: '1234567890' galleryUrl: 'https://xquik.com/gallery/abc123' cacheHit: false '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': description: Tweet media source not found content: application/json: schema: *error-schema example: error: 'tweet_not_found' message: 'Tweet not found.' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '424': $ref: '#/components/responses/XApiError' /x/profile: patch: operationId: updateProfile description: Updates editable fields on a connected X profile. x-write-action: update_profile summary: Update X profile tags: [X Write] security: *api-auth parameters: *write-idempotency-parameters requestBody: required: true description: Account and profile fields to update (name, bio, location, website). content: application/json: schema: type: object required: [account] properties: account: type: string maxLength: 64 description: X account (@username or ID) whose profile to update example: '@elonmusk' name: type: string minLength: 1 maxLength: 50 description: Display name, 1 to 50 characters. An emoji counts as 2. example: 'Example Name' description: type: string maxLength: 160 description: Bio, up to 160 characters. An emoji counts as 2. example: 'CEO of Tesla, SpaceX, and X' location: type: string maxLength: 30 description: Location, up to 30 characters. An emoji counts as 2. example: 'Austin, TX' url: type: string maxLength: 100 description: Website URL example: 'https://x.com' example: account: '@elonmusk' name: 'Example Name' description: 'description_value' location: 'location_value' url: 'https://xquik.com/example' responses: *write-responses /x/profile/avatar: patch: operationId: updateAvatar description: Replaces the avatar on a connected X profile. x-write-action: update_avatar summary: Update profile avatar tags: [X Write] security: *api-auth parameters: *write-idempotency-parameters requestBody: required: true description: Account and avatar image file or HTTPS image URL (max 15 MiB). content: multipart/form-data: schema: type: object required: [account, file] properties: account: type: string maxLength: 64 description: X account (@username or ID) whose avatar to update example: '@elonmusk' file: type: string maxLength: 15728640 format: binary description: Avatar image (max 15 MiB) example: 'binary-content' example: account: '@elonmusk' file: 'file_value' application/json: schema: type: object required: [account, url] properties: account: type: string maxLength: 64 description: X account (@username or ID) receiving avatar from URL example: '@elonmusk' url: type: string maxLength: 2048 format: uri description: HTTPS URL to the avatar image to download example: 'https://example.com/avatar.png' example: account: '@elonmusk' url: 'https://example.com/avatar.png' responses: *media-write-responses /x/profile/banner: patch: operationId: updateBanner description: Replaces the banner on a connected X profile. x-write-action: update_banner summary: Update profile banner tags: [X Write] security: *api-auth parameters: *write-idempotency-parameters requestBody: required: true description: Account and banner image file or HTTPS image URL (max 15 MiB). content: multipart/form-data: schema: type: object required: [account, file] properties: account: type: string maxLength: 64 description: X account (@username or ID) whose banner to update example: '@elonmusk' file: type: string maxLength: 15728640 format: binary description: Banner image (max 15 MiB) example: 'binary-content' example: account: '@elonmusk' file: 'file_value' application/json: schema: type: object required: [account, url] properties: account: type: string maxLength: 64 description: X account (@username or ID) receiving banner from URL example: '@elonmusk' url: type: string maxLength: 2048 format: uri description: HTTPS URL to the banner image to download example: 'https://example.com/banner.png' example: account: '@elonmusk' url: 'https://example.com/banner.png' responses: *media-write-responses /x/communities: post: operationId: createCommunity description: Creates an X Community through a connected account. x-write-action: create_community summary: Create Community tags: [X Write] security: *api-auth parameters: *write-idempotency-parameters requestBody: required: true description: Account, community name, and optional description. content: application/json: schema: type: object required: [account, name] properties: account: type: string maxLength: 64 description: X account (@username or ID) creating the community example: '@elonmusk' name: type: string minLength: 1 maxLength: 100 description: Community name, 1 to 100 characters, as X takes it example: 'Example Name' description: type: string maxLength: 640 description: Community description example: 'A community for Tesla enthusiasts' example: account: '@elonmusk' name: 'Example Name' description: 'A community for Tesla enthusiasts' responses: *write-responses /x/communities/{id}: delete: operationId: deleteCommunity description: Deletes an owned X Community through a connected account. x-write-action: delete_community summary: Delete Community tags: [X Write] security: *api-auth parameters: &resource-write-parameters - $ref: '#/components/parameters/WriteIdempotencyKey' - $ref: '#/components/parameters/CommunityWriteId' requestBody: required: true description: Account, plus the community name to confirm the deletion. content: application/json: schema: type: object required: [account, community_name] properties: account: type: string maxLength: 64 description: X account (@username or ID) deleting the community example: '@elonmusk' community_name: type: string maxLength: 100 description: Community name for confirmation example: 'Tesla Fans' example: account: '@elonmusk' community_name: 'Tesla Fans' responses: *write-responses /x/communities/{id}/join: post: operationId: joinCommunity description: Joins an X Community through a connected account. x-write-action: join_community summary: Join Community tags: [X Write] security: *api-auth parameters: *resource-write-parameters requestBody: required: true description: Account to join the community. content: *x-account-body-content responses: *write-responses delete: operationId: leaveCommunity description: Leaves an X Community through a connected account. x-write-action: leave_community summary: Leave Community tags: [X Write] security: *api-auth parameters: *resource-write-parameters requestBody: required: true description: Account to leave the community. content: *x-account-body-content responses: *write-responses # ── X Accounts ─────────────────────────────────────────── /x/accounts: get: operationId: listXAccounts description: > Returns connected accounts in creation order. Omit pagination for up to 10,000 accounts. Send limit or cursor for legacy pagination. summary: List connected X accounts tags: [X Accounts] security: *api-auth parameters: *limit-after-parameters responses: '200': description: X account list content: application/json: schema: type: object required: [accounts] properties: accounts: type: array items: $ref: '#/components/schemas/XAccount' example: - id: '42' xUserId: '9876543210' xUsername: 'elonmusk' status: 'active' health: 'healthy' createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-03-10T08:30:00Z' hasMore: type: boolean description: Present on cursor-paginated responses. example: false nextCursor: type: string description: Pass unchanged as cursor when hasMore is true. example: 'MjAyNi0wMS0wMVQwMDowMDowMC4wMDBafDQy' example: accounts: - id: '42' xUserId: '9876543210' xUsername: 'elonmusk' status: 'active' health: 'healthy' createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-03-10T08:30:00Z' hasMore: false '400': description: Invalid account list cursor or limit content: application/json: schema: *error-schema example: error: invalid_input message: Invalid account list cursor or limit. '401': *unauthenticated-response '429': *rate-limit-exceeded-response-2 post: operationId: connectXAccount x-mcp-exclusion-reason: &x-login-browser-auth X account sign-in & removal require browser auth. description: Starts an X account connection flow. Needs a dashboard session, so X credentials never pass through an API key. summary: Connect X account tags: [X Accounts] security: [{ cookieSession: [] }] requestBody: required: true description: X credentials (username, email, password) and the Authenticator App 2FA secret required for a durable connection. content: application/json: schema: type: object required: [username, email, password, totp_secret] properties: username: type: string maxLength: 16 pattern: '^@?[A-Za-z0-9_]{1,15}$' description: X username of the account to connect, with or without @ example: 'your_x_username' email: type: string maxLength: 254 description: Account email example: 'account@example.invalid' password: type: string maxLength: 1024 description: Account password example: '' totp_secret: type: string maxLength: 512 description: Authenticator App TOTP secret required for durable login example: '' example: username: 'your_x_username' email: 'account@example.invalid' password: '' totp_secret: '' responses: '201': description: X account connected after verification content: application/json: schema: $ref: '#/components/schemas/SanitizedXAccount' example: { id: '42', xUserId: '9876543210', xUsername: elonmusk, status: active, health: healthy, createdAt: '2025-01-15T12:00:00Z', } '202': description: Connection continues or needs an email code headers: Cache-Control: description: Prevents caching. Present when the response status is `pending`. schema: &no-store-header type: string const: no-store Location: description: Status URL. Present when the response status is `pending`. schema: type: string example: '/api/v1/x/account-connection-attempts/xatt_0123456789abcdef0123456789abcdef' Retry-After: description: Seconds before the next poll when the attempt remains pending. schema: type: integer minimum: 0 example: 3 content: application/json: schema: $ref: '#/components/schemas/XAccountConnectionContinuation' '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '409': $ref: '#/components/responses/ConnectAlreadyConnected' '422': $ref: '#/components/responses/ConnectLoginFailed' '429': $ref: '#/components/responses/ConnectRateLimitExceeded' '502': $ref: '#/components/responses/ConnectUserLookupFailed' '503': $ref: '#/components/responses/ConnectServiceUnavailable' /x/account-connection-attempts/{id}: get: operationId: getXAccountConnectionAttempt x-mcp-exclusion-reason: *x-login-browser-auth description: Returns progress for an X account connection attempt. Needs a dashboard session. summary: Get X account connection status tags: [X Accounts] security: [{ cookieSession: [] }] parameters: - $ref: '#/components/parameters/ConnectionAttemptId' responses: '200': description: Current X account connection status headers: Cache-Control: description: Prevents caching of connection status. schema: *no-store-header Retry-After: description: Seconds before checking again. Present when the response status is `pending`. schema: type: integer minimum: 0 example: 3 content: application/json: schema: x-stainless-naming: csharp: type_name: AccountConnectionAttemptRetrieveResponse oneOf: - $ref: '#/components/schemas/XAccountConnectionAttemptPending' - $ref: '#/components/schemas/XAccountConnectionAttemptSuccess' - $ref: '#/components/schemas/XAccountConnectionAttemptFailed' - $ref: '#/components/schemas/XAccountConnectionChallenge' discriminator: propertyName: status mapping: pending: '#/components/schemas/XAccountConnectionAttemptPending' success: '#/components/schemas/XAccountConnectionAttemptSuccess' failed: '#/components/schemas/XAccountConnectionAttemptFailed' requires_email_code: '#/components/schemas/XAccountConnectionChallenge' example: object: 'x_account_connection_attempt' id: 'xatt_0123456789abcdef0123456789abcdef' status: 'pending' pollAfterMs: 3000 '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '429': *rate-limit-exceeded-response-2 /x/account-connection-challenges/{id}/submit: post: operationId: submitXAccountConnectionChallenge x-mcp-exclusion-reason: *x-login-browser-auth description: Submits the email code requested during X account connection. Needs a dashboard session. summary: Submit X account email verification code tags: [X Accounts] security: [{ cookieSession: [] }] parameters: - $ref: '#/components/parameters/ConnectionChallengeId' requestBody: required: true description: Email verification code requested during account connection. content: application/json: schema: type: object required: [email_code] properties: email_code: type: string minLength: 4 maxLength: 64 description: Code sent to the account email. example: '' example: email_code: '' responses: '201': description: X account connected content: application/json: schema: $ref: '#/components/schemas/SanitizedXAccount' '202': description: Email verification code required content: application/json: schema: $ref: '#/components/schemas/XAccountConnectionChallenge' '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '404': *not-found-response '409': description: Verification challenge is no longer active content: application/json: schema: *error-schema example: error: 'connection_challenge_inactive' message: 'Connection challenge is no longer active.' '410': description: Verification code expired content: application/json: schema: *error-schema example: error: 'connection_challenge_expired' message: 'Verification code expired. Start again.' '422': $ref: '#/components/responses/ConnectLoginFailed' '429': *rate-limit-exceeded-response-2 '503': $ref: '#/components/responses/ConnectServiceUnavailable' /x/accounts/{id}: get: operationId: getXAccount description: Returns 1 connected X account and its current status. summary: Get X account details tags: [X Accounts] security: *api-auth parameters: *resource-id-parameters responses: '200': description: X account details content: application/json: schema: $ref: '#/components/schemas/XAccountDetail' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response-2 delete: operationId: disconnectXAccount x-mcp-exclusion-reason: *x-login-browser-auth description: Disconnects 1 X account and removes stored session access. Needs a dashboard session, since only a new sign-in restores the account. summary: Disconnect X account tags: [X Accounts] security: [{ cookieSession: [] }] parameters: *resource-id-parameters responses: '200': $ref: '#/components/responses/Success' '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '404': *not-found-response '429': *rate-limit-exceeded-response-2 /x/accounts/{id}/reauth: post: operationId: reauthXAccount x-mcp-exclusion-reason: *x-login-browser-auth description: Starts re-authentication for an existing X account connection. Needs a dashboard session, so X credentials never pass through an API key. summary: Re-authenticate X account tags: [X Accounts] security: [{ cookieSession: [] }] parameters: *resource-id-parameters requestBody: required: true description: Updated password and optional fields for re-authentication. content: application/json: schema: type: object required: [password] properties: password: type: string maxLength: 1024 description: Updated account password example: '' totp_secret: type: string maxLength: 512 description: Replacement Authenticator App TOTP secret. Omit it to reuse the saved secret. example: '' email: type: string maxLength: 254 description: Email for the X account. It replaces the stored email. example: 'account@example.invalid' example: password: '' totp_secret: '' email: 'account@example.invalid' responses: '200': description: Re-authenticated content: application/json: schema: $ref: '#/components/schemas/SanitizedXAccount' '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '404': $ref: '#/components/responses/ReauthAccountNotFound' '422': $ref: '#/components/responses/ConnectLoginFailed' '429': $ref: '#/components/responses/ConnectLoginCooldown' '503': $ref: '#/components/responses/ConnectServiceUnavailable' /x/accounts/bulk-retry: post: operationId: bulkRetryXAccounts x-mcp-exclusion-reason: *x-login-browser-auth summary: Bulk retry temporarily failed X accounts description: > Clears loginFailedAt and loginFailureReason for every account with a transient or automated failure reason. Each can then retry on its next use. Name accounts in accountIds to retry only those. Needs a dashboard session, since each retry signs in to X again. tags: [X Accounts] security: [{ cookieSession: [] }] requestBody: required: false description: Leave the body out to retry every account with a transient or automated failure. content: application/json: schema: type: object additionalProperties: false properties: accountIds: type: array minItems: 1 maxItems: 1000 example: ['1', '2'] description: IDs of the X accounts to retry. Accounts that failed for another reason, or belong to someone else, stay as they are. items: oneOf: - type: string pattern: '^(xacct_)?[1-9][0-9]*$' maxLength: 25 example: '1' - type: integer minimum: 1 example: 1 example: accountIds: ['1', '2'] responses: '200': description: Accounts cleared for retry content: application/json: schema: type: object required: [cleared] properties: cleared: type: integer minimum: 0 description: Number of accounts cleared example: 3 example: cleared: 3 '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '429': *rate-limit-exceeded-response-2 # ── Trends ─────────────────────────────────────────────── /trends: get: operationId: getTrends description: Returns current regional trends through the compatibility route. Each request costs 1 credit, however many trends it returns. summary: Get trending hashtags and topics by region (alias) tags: - Trends security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - name: woeid in: query schema: type: integer minimum: 1 default: 1 description: 'The WOEID of any place X lists trends for (1=Worldwide, 23424977=US, 23424975=UK, 23424969=Turkey). List places with GET /x/trends/locations.' - name: count in: query description: Number of trending topics returned (1-50, default 30) schema: type: integer default: 30 minimum: 1 maximum: 50 - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Trending topics content: application/json: schema: type: object required: [trends, total, woeid] properties: trends: type: array items: type: object required: [name] properties: name: type: string example: '#AI' description: type: string example: 'Artificial intelligence discussions' query: type: string example: '%23AI' promotedContent: type: [string, 'null'] description: Promotion ID for this trend, or null when organic. rank: *integer-example-one tweetVolume: type: [integer, 'null'] minimum: 0 description: Estimated post volume for this trend. example: 250000 url: type: string format: uri description: Search URL associated with this trend. example: - name: '#AI' rank: 1 total: type: integer minimum: 0 example: 30 woeid: *integer-example-one example: trends: *trends-example total: 30 woeid: 1 '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '502': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/XApiError' '503': { $ref: '#/components/responses/ReadBusy' } # ── Support Tickets ───────────────────────────────────── /support/attachments/{id}: get: operationId: downloadSupportAttachment x-mcp-exclusion-reason: *binary-rest summary: Download support ticket media description: > Streams an authenticated user's support image or video. Video requests support 1 standard byte range for seeking and resumable playback. tags: [Support] security: *api-auth parameters: - name: id in: path required: true schema: type: string maxLength: 28 pattern: '^att_[0-9a-f]{24}$' description: Support attachment public ID. Another shape gets 400 `invalid_id`. example: 'att_a1b2c3d4e5f6a1b2c3d4e5f6' - name: Range in: header required: false schema: type: string maxLength: 45 pattern: '^bytes=(?:[0-9]{1,19}-[0-9]{0,19}|-[0-9]{1,19})$' description: Optional single byte range. Each position takes up to 19 digits. example: 'bytes=0-1048575' responses: '200': description: Complete image or video bytes content: *binary-download-content '206': description: Requested partial video bytes content: *binary-download-content '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '416': description: Invalid or unsatisfiable byte range content: application/json: schema: *error-schema example: error: 'invalid_range' message: 'Use one valid byte range.' '429': *rate-limit-exceeded-response-2 /support/tickets: post: operationId: createTicket description: Creates a support ticket with an initial message. summary: Create a support ticket tags: [Support] security: *api-auth parameters: - $ref: '#/components/parameters/SupportIdempotencyKey' requestBody: required: true description: Ticket subject and message body. content: application/json: schema: allOf: - $ref: '#/components/schemas/SupportMessageSubmission' - $ref: '#/components/schemas/SupportTicketSubjectSubmission' example: subject: 'Cannot connect X account' body: 'I am unable to connect my X account. Please help.' multipart/form-data: example: subject: 'Cannot connect X account' body: 'I am unable to connect my X account.' attachments: ['screen.png'] schema: allOf: - $ref: '#/components/schemas/SupportMultipartSubmission' - $ref: '#/components/schemas/SupportTicketSubjectSubmission' responses: '200': description: Original ticket replayed after a safe retry headers: Idempotency-Replayed: description: Present as true when replaying the same request. schema: &true-header type: string const: 'true' content: &support-receipt-content application/json: schema: $ref: '#/components/schemas/SupportReceipt' example: publicId: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' attachments: [] '201': description: Ticket created content: *support-receipt-content '400': *invalid-input-response '401': *unauthenticated-response '409': description: Idempotency-Key was reused with different content. content: application/json: schema: *error-schema example: error: 'idempotency_key_conflict' message: 'Reuse this Idempotency-Key only with the original request.' '429': *rate-limit-exceeded-response-2 get: operationId: listTickets description: > Returns support tickets owned by the authenticated user, latest activity first. summary: List user's support tickets tags: [Support] security: *api-auth parameters: *list-limit-after-parameters responses: '200': description: List of tickets content: application/json: schema: type: object required: [tickets, hasMore] properties: tickets: type: array items: type: object required: [ publicId, subject, status, messageCount, createdAt, updatedAt, ] properties: publicId: &ticket-id-example-schema type: string example: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' subject: type: string example: 'Cannot connect X account' status: type: string enum: [open, in_progress, resolved, closed] example: 'open' messageCount: type: integer minimum: 1 example: 2 createdAt: *created-at-schema updatedAt: &update-time-example-schema type: string format: date-time example: '2025-01-16T09:30:00Z' example: - publicId: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' subject: 'Cannot connect X account' status: 'open' messageCount: 2 createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-01-16T09:30:00Z' hasMore: *boolean-example-false nextCursor: *short-id-example-schema example: tickets: - publicId: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' subject: 'Cannot connect X account' status: 'open' messageCount: 2 createdAt: '2025-01-15T12:00:00Z' updatedAt: '2025-01-16T09:30:00Z' hasMore: false '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response-2 /support/tickets/{id}: get: operationId: getTicket description: Returns 1 support ticket with its message history. summary: Get ticket with all messages tags: [Support] security: *api-auth parameters: - name: id in: path required: true schema: type: string maxLength: 28 pattern: '^tkt_[0-9a-f]{24}$' description: Support ticket public ID. Another shape gets 400 `invalid_id`. example: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' responses: '200': description: Ticket detail content: application/json: schema: type: object required: [publicId, subject, status, createdAt, updatedAt, messages] properties: publicId: *ticket-id-example-schema subject: type: string example: 'Cannot connect X account' status: type: string enum: [open, in_progress, resolved, closed] example: 'open' createdAt: *created-at-schema updatedAt: *update-time-example-schema messages: type: array items: type: object required: [body, sender, createdAt, attachments] properties: body: type: string example: 'I am unable to connect my X account.' sender: type: string enum: [user, support, system] example: 'user' createdAt: *created-at-schema attachments: type: array items: $ref: '#/components/schemas/SupportAttachment' example: - body: 'I am unable to connect my X account.' sender: 'user' createdAt: '2025-01-15T12:00:00Z' attachments: [] '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response-2 patch: operationId: updateTicketStatus description: Changes the open or closed state of a support ticket. summary: Update ticket status tags: [Support] security: *api-auth parameters: - name: id in: path required: true schema: type: string maxLength: 28 pattern: '^tkt_[0-9a-f]{24}$' description: Support ticket public ID to update. Another shape gets 400 `invalid_id`. example: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' requestBody: required: true description: New ticket status (open, resolved, or closed). content: application/json: schema: type: object required: [status] properties: status: type: string enum: [open, resolved, closed] example: 'resolved' example: status: 'resolved' responses: '200': description: Status updated content: application/json: schema: type: object required: [publicId, status] properties: publicId: *ticket-id-example-schema status: type: string enum: [open, resolved, closed] example: 'resolved' example: publicId: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' status: 'resolved' '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response-2 /support/tickets/{id}/messages: post: operationId: addTicketMessage description: Adds a message to an existing support ticket. summary: Reply to a support ticket tags: [Support] security: *api-auth parameters: - name: id in: path required: true schema: type: string maxLength: 28 pattern: '^tkt_[0-9a-f]{24}$' description: Support ticket public ID for the reply. Another shape gets 400 `invalid_id`. example: 'tkt_a1b2c3d4e5f6a1b2c3d4e5f6' - $ref: '#/components/parameters/SupportIdempotencyKey' requestBody: required: true description: Reply message body (max 10,000 characters). content: application/json: schema: $ref: '#/components/schemas/SupportMessageSubmission' example: body: 'Thank you for the update.' multipart/form-data: example: body: 'Thank you for the update.' attachments: ['details.png'] schema: $ref: '#/components/schemas/SupportMultipartSubmission' responses: '200': description: Original message replayed after a safe retry headers: Idempotency-Replayed: description: Set to true when this message replays. schema: *true-header content: *support-receipt-content '201': description: Message added content: *support-receipt-content '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '409': description: Reply key was reused with different message content. content: application/json: schema: *error-schema example: error: 'idempotency_key_conflict' message: 'Reuse this Idempotency-Key only with the original request.' '429': *rate-limit-exceeded-response-2 /guest-wallets: post: operationId: createGuestWallet x-mcp-exclusion-reason: &guest-wallet-rest Guest wallet billing remains direct REST. summary: Create an accountless prepaid wallet checkout description: > Create a one-use hosted checkout after the user confirms $10-$250 USD. The request creates no charge. It returns a paid-read API key without an Xquik account. Idempotent replays return the same key. tags: [Guest Wallets] security: [{}] parameters: &guest-idempotency-parameters - $ref: '#/components/parameters/GuestIdempotencyKey' requestBody: required: true description: Confirmed USD amount in cents. content: &guest-wallet-purchase-request-content application/json: schema: $ref: '#/components/schemas/GuestWalletPurchaseRequest' example: amount_minor: 1000 currency: usd responses: '201': description: Hosted checkout, guest API key, and API status URL. headers: Cache-Control: description: Prevents storage of the secret-bearing response. schema: type: string const: no-store, private Idempotent-Replayed: description: Set to true when this wallet creation replays. schema: *true-header content: application/json: schema: $ref: '#/components/schemas/GuestWalletCreateResponse' example: account_required: false amount: { amount_minor: 1000, currency: usd } api_key: xq_example_returned_once authorization: { header: Authorization, scheme: Bearer } checkout_url: https://checkout.example/guest/example credential_notice: Store api_key and the Idempotency-Key securely before sharing checkout_url. No email recovery is available. credits: '66666' expires_at: '2026-07-13T13:00:00.000Z' instructions: Give checkout_url to the user. They must complete payment on the hosted checkout page. Never submit payment for them. After payment, poll status_url every poll_after_seconds until latest_purchase.status is no longer pending. poll_after_seconds: 2 purchase_id: gp_example requires_user_interaction: true status: pending status_url: https://xquik.com/api/v1/guest-wallets/status wallet_id: gw_example '400': *invalid-input-response '409': description: Idempotency-Key was reused with a different request. content: &guest-wallet-idempotency-conflict-content application/json: schema: *error-schema example: error: 'idempotency_conflict' message: 'Reuse this Idempotency-Key only with the original request.' '410': description: Checkout expired or can no longer be used. content: &guest-wallet-checkout-unavailable-content application/json: schema: *error-schema example: error: 'checkout_unavailable' message: 'Checkout unavailable. Retry with a new Idempotency-Key.' '413': description: Request body is too large. content: &guest-wallet-body-too-large-content application/json: schema: *error-schema example: error: 'body_too_large' message: 'Request body is too large.' '415': description: Content-Type must be application/json. content: &guest-wallet-media-type-content application/json: schema: *error-schema example: error: 'unsupported_media_type' message: 'Send Content-Type: application/json.' '423': description: Guest wallet is unavailable. content: &guest-wallet-unavailable-content application/json: schema: *error-schema example: error: 'guest_wallet_unavailable' message: 'Guest wallet unavailable. Create a new wallet or contact support.' '429': $ref: '#/components/responses/GuestWalletRateLimited' '503': description: Guest wallet checkout is unavailable. content: &guest-wallet-service-unavailable-content application/json: schema: *error-schema example: error: 'guest_wallets_unavailable' message: 'Guest wallet checkout is temporarily unavailable.' /guest-wallets/topups: post: operationId: topUpGuestWallet x-mcp-exclusion-reason: *guest-wallet-rest summary: Create another guest wallet checkout description: > Create a one-use hosted checkout after the user confirms a $10-$250 USD amount for an existing paid-read guest key. The key remains the same. This request creates no charge and never redirects through Xquik. tags: [Guest Wallets] security: [{ apiKey: [] }] parameters: *guest-idempotency-parameters requestBody: required: true description: Confirmed top-up amount in USD cents. content: *guest-wallet-purchase-request-content responses: '201': description: Hosted checkout and API status URL. headers: Cache-Control: description: Prevents caching the top-up checkout response. schema: type: string const: no-store, private Idempotent-Replayed: description: Set to true when this top-up replays. schema: *true-header content: application/json: schema: $ref: '#/components/schemas/GuestWalletTopupResponse' example: account_required: false amount: { amount_minor: 1000, currency: usd } checkout_url: https://checkout.example/guest/example credits: '66666' expires_at: '2026-07-13T13:00:00.000Z' instructions: Give checkout_url to the user. They must complete payment on the hosted checkout page. Never submit payment for them. After payment, poll status_url every poll_after_seconds until latest_purchase.status is no longer pending. poll_after_seconds: 2 purchase_id: gp_example requires_user_interaction: true status: pending status_url: https://xquik.com/api/v1/guest-wallets/status wallet_id: gw_example '400': *invalid-input-response '401': *unauthenticated-response '409': description: Top-up key was reused with a different request. content: *guest-wallet-idempotency-conflict-content '410': description: Top-up checkout expired or became unavailable. content: *guest-wallet-checkout-unavailable-content '413': description: Top-up request body is too large. content: *guest-wallet-body-too-large-content '415': description: Top-up requires Content-Type application/json. content: *guest-wallet-media-type-content '423': description: Guest wallet cannot accept a top-up. content: *guest-wallet-unavailable-content '429': $ref: '#/components/responses/GuestWalletRateLimited' '503': description: Guest wallet top-up checkout is unavailable. content: *guest-wallet-service-unavailable-content /guest-wallets/status: get: operationId: getGuestWalletStatus x-mcp-exclusion-reason: *guest-wallet-rest summary: Get guest wallet and payment status description: > Poll after payment. Use usable to decide whether paid reads can run. An active wallet can remain usable while a top-up is pending. A new wallet becomes usable only after Xquik verifies payment. Send the guest key as `Authorization: Bearer xq_...` tags: [Guest Wallets] security: [{ apiKey: [] }] responses: '200': description: Guest wallet status without exposing the API key. headers: Cache-Control: description: Prevents storage of wallet status. schema: type: string const: no-store, private content: application/json: schema: $ref: '#/components/schemas/GuestWalletStatusResponse' example: balance: '66666' latest_purchase: amount: { amount_minor: 1000, currency: usd } checkout_url: null credits: '66666' expires_at: '2026-07-13T13:00:00.000Z' purchase_id: gp_example status: paid poll_after_seconds: null scope: paid_reads status: active top_up: method: POST path: /api/v1/guest-wallets/topups usable: true wallet_id: gw_example '401': *unauthenticated-response '429': $ref: '#/components/responses/GuestWalletRateLimited' /credits: get: operationId: getCredits description: Returns the account credit balance and usage context. summary: Get credits balance tags: - Subscribe security: *api-auth responses: '200': description: Credits balance and usage content: application/json: schema: type: object required: [ auto_topup_amount_dollars, auto_topup_enabled, auto_topup_stopped, auto_topup_threshold, balance, lifetime_purchased, lifetime_used, ] properties: auto_topup_amount_dollars: type: number description: Configured dollar amount for each automatic top-up. example: 10 auto_topup_enabled: *boolean-example-false auto_topup_stopped: type: boolean description: Whether declined charges stopped automatic top-up while it is enabled. It stops after 3 declines in a row on 1 card. A paid top-up, a paid plan renewal, or the next automatic top-up on a new card clears it. example: false auto_topup_threshold: type: string description: Credit balance threshold that triggers automatic top-up when enabled, as a bigint string. example: '50000' balance: type: string description: Current credit balance as a bigint string, which keeps precision above Number.MAX_SAFE_INTEGER. example: '50000' lifetime_purchased: type: string description: Lifetime purchased credits as a bigint string. example: '200000' lifetime_used: type: string description: Lifetime consumed credits as a bigint string. example: '150000' example: auto_topup_amount_dollars: 10 auto_topup_enabled: false auto_topup_stopped: false auto_topup_threshold: '50000' balance: '50000' lifetime_purchased: '200000' lifetime_used: '150000' '401': *unauthenticated-response '429': *rate-limit-exceeded-response-2 /credits/topup: post: operationId: topUpCredits x-mcp-exclusion-reason: *browser-checkout summary: Create credit top-up checkout description: > Create a hosted checkout only after the user confirms. The request never completes payment or adds credits. tags: - Subscribe security: *api-auth requestBody: required: true description: Confirmed dollar amount for the credit top-up checkout. content: application/json: schema: type: object required: [dollars] properties: dollars: type: integer description: Amount to top up in US dollars. Minimum 10. minimum: 10 example: 10 locale: type: string maxLength: 35 description: Optional site language for Stripe's return page. An unsupported language uses en, the default. example: en example: dollars: 10 locale: 'en' responses: '200': description: Top-up checkouts content: application/json: schema: type: object required: [url, redirect_url] properties: redirect_url: type: string format: uri description: Stable Xquik redirect URL for the active checkout. example: 'https://xquik.com/api/v1/credits/topup/redirect?session_id=checkout_example' url: type: string format: uri description: > Same stable Xquik redirect URL as redirect_url. The response never exposes the hosted checkout URL. example: 'https://xquik.com/api/v1/credits/topup/redirect?session_id=checkout_example' example: redirect_url: 'https://xquik.com/api/v1/credits/topup/redirect?session_id=checkout_example' url: 'https://xquik.com/api/v1/credits/topup/redirect?session_id=checkout_example' '400': *invalid-input-response '401': *unauthenticated-response '429': *rate-limit-exceeded-response-2 /credits/topup/redirect: get: operationId: redirectCreditTopupCheckout x-mcp-exclusion-reason: *browser-checkout description: Redirects to the active hosted top-up checkout. summary: Redirect to an active top-up payment page tags: - Subscribe security: [] parameters: - name: session_id in: query required: true schema: type: string minLength: 1 maxLength: 255 pattern: '\S' description: Billing session ID returned by the top-up billing flow. responses: '303': description: Redirects to the active payment page. headers: Location: description: Payment page URL. schema: &uri-string type: string format: uri '400': description: Missing or invalid top-up billing session ID. content: application/json: schema: *error-schema example: error: invalid_input '404': description: Top-up billing session not found. content: application/json: schema: *error-schema example: error: not_found '410': description: Top-up billing session is closed or expired. content: application/json: schema: *error-schema examples: closed: value: { error: closed } expired: value: { error: expired } '502': description: Payment page lookup failed. content: application/json: schema: *error-schema example: error: missing_url /credits/topup/status: get: operationId: getCreditTopupStatus x-mcp-exclusion-reason: *browser-checkout description: Returns verification status for a credit top-up. summary: Get top-up billing status tags: - Subscribe security: *api-auth parameters: - name: session_id in: query required: true schema: type: string maxLength: 255 description: Top-up session ID to inspect. responses: '200': description: Top-up billing status content: application/json: schema: type: object required: [status] properties: amount_dollars: anyOf: - type: integer minimum: 10 - type: 'null' description: Dollar amount requested for the top-up. example: 25 credits: type: string description: Bigint string credit amount granted or pending. example: '166666' status: type: string enum: [paid, processing, failed, expired] example: paid example: amount_dollars: 25 credits: '166666' status: paid '400': *invalid-input-response '401': *unauthenticated-response '404': *not-found-response '429': *rate-limit-exceeded-response-2 /credits/quick-topup: post: operationId: quickTopUpCredits x-mcp-exclusion-reason: *browser-checkout description: Charges a saved payment method only after explicit confirmation. summary: Charge saved card for credits tags: - Subscribe security: [{ cookieSession: [] }] requestBody: required: true description: Dollar amount to charge the saved payment method. content: application/json: schema: type: object required: [dollars] properties: dollars: type: number description: Dollar amount for the top-up minimum: 10 maximum: 500 example: 25 example: dollars: 25 responses: '200': description: Quick top-up result content: application/json: schema: oneOf: - type: object required: [outcome, balance, credits] properties: outcome: type: string const: charged balance: type: string description: Updated credit balance as a bigint string. example: '1450' credits: type: string description: Credits added by this top-up as a bigint string. example: '1000' - type: object required: [outcome, clientSecret] properties: outcome: type: string const: requires_action clientSecret: type: string description: Payment client secret for completing authentication. example: pi_example_secret_example - type: object required: [outcome] properties: outcome: type: string const: no_payment_method - type: object required: [outcome] properties: outcome: type: string const: declined examples: charged: summary: Payment succeeded value: outcome: charged balance: '1450' credits: '1000' requiresAction: summary: Additional authentication required value: outcome: requires_action clientSecret: pi_example_secret_example noPaymentMethod: summary: No saved payment method value: outcome: no_payment_method declined: summary: Saved payment method declined value: outcome: declined '400': *invalid-input-response '401': *unauthenticated-response '403': $ref: '#/components/responses/SessionRequired' '429': *rate-limit-exceeded-response-2 /x/tweets/{id}/favoriters: parameters: - $ref: '#/components/parameters/TweetPathId' get: operationId: getTweetFavoriters summary: List visible users who liked a tweet description: > Returns the likers your X account sees. Without your own connected X account, it answers 424 `account_required`. X shows likers only to the post author. tags: - Tweets security: *api-auth parameters: &profile-page-parameters - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/FollowerPageSize' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Visible likers content: *paginated-users-content '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '403': &guest-forbidden-response $ref: '#/components/responses/GuestForbidden' '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/FavoritersUnavailable' /x/users/{id}/tweets: get: operationId: getUserTweets summary: List recent tweets posted by a user description: > For the newest posts of 2 to 20 users, use getBatchUserTweets. For more, use createExtraction with tweet_search_extractor & targetUsernames. Omit mode for automatic maximum coverage. Pass next_cursor unchanged. Unprefixed cursors are legacy. The first page opens with the pinned tweet, flagged isPinned, unless replies are included. Rows stay newest first. x.com's Posts tab groups self-threads & hides reposts. Send retweets=exclude to drop reposts. tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/LegacyPaginationMode' - $ref: '#/components/parameters/AutomaticTweetPageSize' - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/TweetIncludeReplies' - $ref: '#/components/parameters/TweetIncludeParentTweet' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/CardName' - $ref: '#/components/parameters/Source' - $ref: '#/components/parameters/ExcludeSource' - $ref: '#/components/parameters/Geocode' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/Near' - $ref: '#/components/parameters/Within' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/Safe' - $ref: '#/components/parameters/News' - $ref: '#/components/parameters/Keywords' - $ref: '#/components/parameters/ListId' - $ref: '#/components/parameters/Place' - $ref: '#/components/parameters/PlaceCountry' - $ref: '#/components/parameters/PointRadius' - $ref: '#/components/parameters/BoundingBox' - $ref: '#/components/parameters/AdvancedQuery' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: User tweets list content: &paginated-tweets-content application/json: schema: $ref: '#/components/schemas/PaginatedTweets' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': *user-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/users/{id}/replies: get: operationId: getUserReplies summary: List a user's With Replies timeline description: >- Returns target-authored posts & replies, without other authors' context. Omit mode for automatic maximum coverage. Pass next_cursor unchanged. Unprefixed cursors are legacy. It never opens with the pinned tweet. tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/LegacyPaginationMode' - $ref: '#/components/parameters/AutomaticTweetPageSize' - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/TweetIncludeParentTweet' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/CardName' - $ref: '#/components/parameters/Source' - $ref: '#/components/parameters/ExcludeSource' - $ref: '#/components/parameters/Geocode' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/Near' - $ref: '#/components/parameters/Within' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/Safe' - $ref: '#/components/parameters/News' - $ref: '#/components/parameters/Keywords' - $ref: '#/components/parameters/ListId' - $ref: '#/components/parameters/Place' - $ref: '#/components/parameters/PlaceCountry' - $ref: '#/components/parameters/PointRadius' - $ref: '#/components/parameters/BoundingBox' - $ref: '#/components/parameters/AdvancedQuery' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: User timeline with replies content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': *user-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/users/{id}/likes: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserLikes description: Returns your X account's likes. Without your own connected X account, it answers 424 `account_required`. Others' likes get 424 `likes_unavailable`. summary: List tweets liked by a user tags: - Users security: *api-auth parameters: &tweet-row-page-parameters - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Liked tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '403': *guest-forbidden-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/media: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserMedia description: Returns public media posts from the selected user. summary: List media tweets posted by a user tags: - Users security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: List of media tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/affiliates: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserAffiliates description: Returns the accounts an organization lists as its affiliates, in X's order. An account without affiliates returns an empty list. summary: List the affiliates of an organization tags: - Users security: *read-auth parameters: *profile-page-parameters responses: '200': description: List of affiliated accounts content: *paginated-users-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/subscriptions: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserSubscriptions description: Returns the creators the selected user subscribes to, in X's order. An account that hides its subscriptions returns an empty list. summary: List the creators a user subscribes to tags: - Users security: *read-auth parameters: *profile-page-parameters responses: '200': description: List of creators content: *paginated-users-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/lists: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserLists description: Returns the public X Lists the selected user created, in X's order, as the profile's Lists tab shows them. Each List costs 1 credit. A protected account answers 403. summary: List the public Lists a user created tags: - Users security: *read-auth parameters: &user-lists-parameters - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: A page of the Lists the user created content: &list-page-content application/json: schema: $ref: '#/components/schemas/PaginatedLists' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '404': $ref: '#/components/responses/UserNotFound' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': $ref: '#/components/responses/RateLimitExceeded' '424': $ref: '#/components/responses/XApiError' /x/users/{id}/list-memberships: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserListMemberships description: Returns the public X Lists that include the selected user, as the profile's List memberships page shows them. Each List costs 1 credit. A protected account answers 403. summary: List the public Lists a user is on tags: - Users security: *read-auth parameters: *user-lists-parameters responses: '200': description: A page of the Lists the user is on content: *list-page-content '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '404': $ref: '#/components/responses/UserNotFound' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': $ref: '#/components/responses/RateLimitExceeded' '424': $ref: '#/components/responses/XApiError' /x/users/{id}/articles: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserArticles description: Returns the posts on the user's Articles tab, newest first. Each post's `article` holds the Article's ID, title, preview, cover & dates. Read the full text with GET /x/articles/{tweetId}. summary: List the Articles a user published tags: - Users security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: List of Article tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/highlights: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserHighlights description: Returns the posts on the user's Highlights tab, in X's order. An account without highlights returns an empty list. summary: List a user's highlighted tweets tags: - Users security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: List of highlighted tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedTimeline' '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/followers-you-know: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getFollowersYouKnow description: Returns the mutual followers your X account sees. Without your own connected X account, it answers 424 `account_required`. summary: List mutual followers between you and a user tags: - Users security: *api-auth parameters: *profile-page-parameters responses: '200': description: Mutual followers content: *paginated-users-content '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '403': *guest-forbidden-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/similar: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getSimilarUsers description: Returns the public accounts X lists as similar to the selected user, in X's order. X can list slightly different accounts on each call. Each account costs 1 credit. summary: List accounts similar to a user tags: - Users security: *read-auth parameters: *profile-page-parameters responses: '200': description: Accounts similar to the user content: *paginated-users-content '400': $ref: '#/components/responses/InvalidInput' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/XApiError' /x/bookmarks: get: operationId: getBookmarks description: Returns your X account's bookmarks. Without your own connected X account, it answers 424 `account_required`. Without X Premium, a folder answers 424 `bookmark_folders_unavailable`. summary: Get bookmarked tweets tags: - Tweets security: *api-auth parameters: - name: folderId in: query schema: type: string description: Optional bookmark folder ID. Folders need X Premium. - name: cursor in: query schema: type: string maxLength: 4096 example: 'DAACCgACGRElMJcAAA' description: Pagination cursor for bookmarks. Also read as next_cursor, next_token, pagination_token or continuation_token. responses: '200': description: List of bookmarked tweets content: *paginated-tweets-content '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '424': $ref: '#/components/responses/XApiError' /x/bookmarks/folders: get: operationId: getBookmarkFolders description: Returns your X account's bookmark folders. Without your own connected X account, it answers 424 `account_required`. Without X Premium, it answers 424 `bookmark_folders_unavailable`. summary: Get bookmark folders tags: - Tweets security: *api-auth parameters: - $ref: '#/components/parameters/CollectionCursor' responses: '200': description: List of bookmark folders content: application/json: schema: type: object required: [folders, has_next_page, next_cursor] properties: folders: type: array items: $ref: '#/components/schemas/BookmarkFolder' example: - id: '1234567890' media: originalImageUrl: 'https://pbs.twimg.com/media/cover.jpg' name: 'Read Later' has_next_page: type: boolean description: Whether another folder page is available example: false next_cursor: type: string description: Cursor for the next folder page example: '' example: folders: - id: '1234567890' media: originalImageUrl: 'https://pbs.twimg.com/media/cover.jpg' name: 'Read Later' has_next_page: false next_cursor: '' '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '424': $ref: '#/components/responses/XApiError' /x/notifications: get: operationId: getNotifications description: Returns your X account's notifications. Without your own connected X account, it answers 424 `account_required`. summary: Get notifications tags: - Users security: *api-auth parameters: - name: type in: query schema: type: string enum: [All, Verified, Mentions] default: All description: Notification type filter. Unrecognized values fall back to All. - $ref: '#/components/parameters/CollectionCursor' responses: '200': description: List of notifications content: application/json: schema: type: object required: [notifications, has_next_page, next_cursor] properties: notifications: type: array items: type: object required: [id] properties: id: *tweet-id-example-schema type: type: string example: 'like' message: type: string example: 'elonmusk liked your tweet' timestamp: *timestamp-text-example-schema example: - id: '1234567890' type: 'like' message: 'elonmusk liked your tweet' timestamp: '2025-01-15T12:00:00Z' has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' example: notifications: - id: '1234567890' type: 'like' message: 'elonmusk liked your tweet' timestamp: '2025-01-15T12:00:00Z' has_next_page: true next_cursor: 'DAACCgACGRElMJcAAA' '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '424': $ref: '#/components/responses/XApiError' /x/timeline: get: operationId: getTimeline description: Returns the home timeline of 1 of your connected X accounts. Without one, it answers 424 `account_required`. A cursor reads the next page from the same account. Results exclude X ads. summary: Get home timeline tags: - Tweets security: *api-auth parameters: - name: seenTweetIds in: query schema: type: string maxLength: 13075 description: Comma-separated tweet IDs to exclude from results. Xquik ignores empty entries. A longer URL fails at the edge before Xquik reads it. - $ref: '#/components/parameters/CollectionCursor' responses: '200': description: List of timeline tweets content: *paginated-tweets-content '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '410': description: Start again without the cursor. content: application/json: schema: *error-schema example: error: 'cursor_account_unavailable' message: 'The X account for this cursor is unavailable. Start again without the cursor.' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '424': $ref: '#/components/responses/XApiError' /x/dm/{userId}/history: get: operationId: getDmHistory description: Returns message history with 1 user for the connected X account. summary: Get DM conversation history tags: - Users security: *api-auth parameters: - $ref: '#/components/parameters/DmUserPathId' - name: account in: query required: true schema: type: string maxLength: 64 description: > X handle (without the `@` prefix) of the connected X account used to read the conversation. The account must be a participant in the conversation. - $ref: '#/components/parameters/CollectionCursor' - name: maxId in: query schema: type: string maxLength: 4096 description: Legacy pagination cursor (backward compat) responses: '200': description: List of DM messages content: application/json: schema: type: object required: [messages, has_next_page, next_cursor] properties: messages: type: array items: type: object required: [id, senderId, receiverId] properties: id: type: string example: '1234567890123456789' text: type: string example: 'Hey, how are you?' description: Text as x.com shows it, with `&`, `<` & `>` decoded. senderId: &user-id-example-schema type: string example: '9876543210' receiverId: *tweet-id-example-schema createdAt: *timestamp-text-example-schema mediaUrl: type: string example: 'https://pbs.twimg.com/dm_media/abc.jpg' description: > URL of attached media (image, GIF, or video). Omitted when the message has no media attachment. example: - id: '1234567890123456789' text: 'Hey, how are you?' senderId: '9876543210' receiverId: '1234567890' has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' example: messages: - id: '1234567890123456789' text: 'Hey, how are you?' senderId: '9876543210' receiverId: '1234567890' has_next_page: true next_cursor: 'DAACCgACGRElMJcAAA' '400': description: > Invalid input. `invalid_user_id` means the path user ID is empty or invalid. `account_required` means the `account` query parameter was missing or empty. `invalid_input` means `account` is over 64 characters. `invalid_cursor` means `cursor` or `maxId` is over 4,096 characters. content: application/json: schema: *error-schema examples: invalidUserId: summary: Invalid user ID value: error: invalid_user_id accountRequired: summary: Account query parameter missing value: error: account_required message: >- Provide ?account= for a connected X account. DM history requires a connected participant account. '401': *unauthenticated-response '402': *payment-required-response '403': description: > DM read forbidden. The connected account may not be in the conversation, or it may be restricted or need reauthentication. Check the error code, then fix the account. content: application/json: schema: *error-schema examples: dmNotPermitted: summary: Account is not a conversation participant value: error: dm_not_permitted message: >- X rejected the DM read. The connected account is not a participant in this conversation, or it needs reauthentication. Reconnect the account on the dashboard and try again. accountRestricted: summary: Connected account is restricted value: error: account_restricted accountNeedsReauth: summary: Connected account needs reauthentication value: error: account_needs_reauth '404': description: Connected X account not found for the authenticated user. content: application/json: schema: *error-schema example: error: account_not_found message: X account not found. Connect it first at /dashboard/account?tab=x-accounts. '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/info: get: operationId: getCommunityInfo description: Returns 1 community's public identity, rules, join question, search tags, membership counts, and the profiles of its creator, admin and previewed members. summary: Get community name, description and member count tags: - Communities security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/CommunityPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Community details content: application/json: schema: type: object required: [community] properties: community: $ref: '#/components/schemas/Community' example: community: id: '1500000000000000000' name: 'Tesla Fans' description: 'A community for Tesla enthusiasts' banner_url: 'https://xquik.com/example' created_at: '2025-01-15T12:00:00Z' join_policy: 'open' member_count: 10000 moderator_count: 5 is_nsfw: false '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/analytics: get: operationId: getCommunityAnalytics summary: Get community activity & growth description: Returns community activity for X's latest period. Includes likes, new members, posts, replies & unique posters. Each metric has a count and a changePercent. Each request costs 1 credit. tags: - Communities security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/CommunityPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Community activity & growth for X's latest period content: application/json: schema: $ref: '#/components/schemas/CommunityAnalytics' example: id: '1493446837214187523' periodEndsAt: '2026-10-16T23:59:59.999Z' metrics: likes: count: 15298 changePercent: -1.2076202776880853 newMembers: count: 557 changePercent: -1.5901060070671376 posts: count: 5108 changePercent: 0.5907837731390311 replies: count: 6851 changePercent: -0.8251302837290099 uniquePosters: count: 1800 changePercent: -0.33222591362126247 '400': $ref: '#/components/responses/InvalidInput' '401': *unauthenticated-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/members: get: operationId: getCommunityMembers description: Returns public member profiles for 1 community. summary: List members of a community tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CommunityPathId' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/LegacyUserPageSize' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of community members content: *paginated-users-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/members/search: get: operationId: searchCommunityMembers summary: Search members of a community by name description: Finds a community's members by name or username, as the search box on X's members page does. X checks up to 10 accounts that match, & the answer holds the members among them, each with its role. Each member costs 1 credit. An answer without members is free. tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CommunityPathId' - $ref: '#/components/parameters/CommunityMemberQuery' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Community members X found for the name content: application/json: schema: $ref: '#/components/schemas/PaginatedUsers' example: users: - id: '641633' username: marckohlbrugge name: Marc Köhlbrugge communityRole: Admin profilePicture: https://pbs.twimg.com/profile_images/1857124042433572864/iMivVaYP_normal.jpg isBlueVerified: true has_next_page: false next_cursor: '' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/moderators: get: operationId: getCommunityModerators description: Returns public moderator profiles for 1 community. summary: List moderators of a community tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CommunityPathId' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of community moderators content: *paginated-users-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/tweets: parameters: - $ref: '#/components/parameters/CommunityPathId' get: operationId: getCommunityTweets description: Returns public tweets posted within 1 community, newest first by default. Send queryType=Top for the posts X ranks highest. The first page opens with the tweet the community pinned, flagged isPinned, as x.com shows it. Each tweet costs 1 credit. summary: List tweets posted in a community tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/CommunityPostOrder' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of community tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/{id}/media: parameters: - $ref: '#/components/parameters/CommunityPathId' get: operationId: getCommunityMedia description: Returns the tweets with photos or videos on 1 community's Media tab, newest first. Each tweet costs 1 credit. summary: List media tweets posted in a community tags: - Communities security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: Media tweets of the community content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/find: get: operationId: findCommunities summary: Find X Communities by keyword description: Returns the communities X finds for a keyword, in X's order. Each community costs 1 credit. To search the tweets in Communities, use /x/communities/search. tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CommunityFindQuery' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Communities X finds for the keyword content: &community-page-content application/json: schema: $ref: '#/components/schemas/CommunityPage' example: communities: &community-rows-example - id: '1472105760389668865' name: 'Tech Twitter' member_count: 121468 is_nsfw: false primary_topic: { name: 'Technology' } banner_url: 'https://pbs.twimg.com/community_banner_img/example.jpg' membersFacepile: - id: '2864203879' profilePicture: 'https://pbs.twimg.com/profile_images/example.jpg' has_next_page: true next_cursor: 'WzM1LjUxMjQ5N10=' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/popular: get: operationId: getPopularCommunities summary: List the most popular X Communities of a topic description: Returns the communities X ranks highest under a topic or subtopic. Name it by topicId or by topic name from /x/communities/topics. Each community costs 1 credit. A missing or unknown topic returns invalid_community_topic & lists the topic names. tags: - Communities security: *read-auth parameters: - $ref: '#/components/parameters/CommunityTopicId' - $ref: '#/components/parameters/CommunityTopicName' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Popular communities of the topic content: *community-page-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/topics: get: operationId: getCommunityTopics summary: List the topics X groups communities under description: Returns the community topics with their subtopics. Pass an ID as topicId, or a name as topic, to /x/communities/popular. Each top-level topic costs 1 credit, its subtopics included. tags: - Communities security: *read-auth parameters: - name: limit in: query schema: type: integer minimum: 1 description: Maximum topics to return. Omit it for every topic. A low credit balance can return fewer. Aliases pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Community topics with their subtopics content: application/json: schema: type: object required: [topics, count] properties: topics: type: array description: Topics in X's order items: $ref: '#/components/schemas/CommunityTopic' example: &community-topics-example - id: '301' name: 'Technology' subtopics: - id: '302' name: 'Artificial Intelligence' - id: '303' name: 'Software' count: type: integer minimum: 0 description: Top-level topics returned & charged example: 1 message: type: string description: What to do next. Present only when X lists no topic. example: 'X listed no community topics. Try again soon.' example: topics: *community-topics-example count: 1 '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/suggested: get: operationId: getSuggestedCommunities summary: List the X Communities X suggests to join description: Returns the communities X suggests, with their full public fields. X picks them per request, so 2 calls can differ. If X suggests none, Xquik asks up to 2 more times. An empty list is free. Each community costs 1 credit. tags: - Communities security: *read-auth parameters: - name: limit in: query schema: type: integer minimum: 1 description: Maximum communities to return. Omit it for every suggestion. A low credit balance can return fewer. Aliases pageSize, count, max_results, maxItems, max_items & per_page. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Communities X suggests content: application/json: schema: type: object required: [communities, count] properties: communities: type: array description: Suggested communities in X's order items: $ref: '#/components/schemas/Community' example: *community-rows-example count: type: integer minimum: 0 description: Communities returned & charged example: 1 message: type: string description: What to do next. Present only when X suggests none. example: 'X suggested no communities. Try again soon.' example: communities: - id: '1472105760389668865' name: 'Tech Twitter' member_count: 121468 is_nsfw: false primary_topic: { name: 'Technology' } banner_url: 'https://pbs.twimg.com/community_banner_img/example.jpg' membersFacepile: - id: '2864203879' profilePicture: 'https://pbs.twimg.com/profile_images/example.jpg' count: 1 '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/search: get: operationId: searchCommunities summary: Search tweets in X Communities by keyword description: > Returns 1 page of tweets, not community records. Add communityId to search 1 Community, or leave it out to search every Community. To find communities by keyword, use /x/communities/find. tags: - Communities security: *read-auth parameters: &communitySearchParameters - $ref: '#/components/parameters/CommunitySearchId' - $ref: '#/components/parameters/CommunityQuery' - $ref: '#/components/parameters/CommunityQueryType' - $ref: '#/components/parameters/CommunityCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: &communitySearchResponses '200': $ref: '#/components/responses/CommunityTweetSearchResults' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/communities/tweets: get: operationId: getAllCommunityTweets summary: Search tweets in X Communities description: > Returns 1 resumable page of tweets. Add communityId to search 1 Community, or leave it out to search every Community. tags: - Communities security: *read-auth parameters: *communitySearchParameters responses: *communitySearchResponses /x/jobs/search: get: operationId: searchJobs summary: Search public X job listings by keyword description: > Returns job listings with title, location, salary, company & apply link. Add filters to narrow them. A closed job does not appear & costs nothing. Follow next_cursor for more. tags: - Jobs security: *read-auth parameters: - name: q in: query required: true schema: { type: string } description: 'Keyword, such as a job title or skill. Its alias is query.' example: engineer - name: location in: query schema: { type: string } description: City, region or country as text, such as Berlin. example: Berlin - name: locationId in: query schema: { type: string } description: > Location ID from GET /x/jobs/locations. Replaces location when both are sent. example: '1720462281849397612' - name: locationType in: query schema: { type: string } description: > Where the work happens. Comma-separated list of onsite, remote & hybrid. Any case works, with spaces or hyphens between words. example: remote,hybrid - name: seniority in: query schema: { type: string } description: > Comma-separated list of intern, entry_level, junior, mid_level, senior, lead, manager & executive. Any case works, with spaces or hyphens between words. example: senior,lead - name: employmentType in: query schema: { type: string } description: > Comma-separated list of full_time, full_time_contract, part_time & contract_to_hire. Any case works, with spaces or hyphens between words. example: full_time - name: company in: query schema: { type: string } description: Company name to match. example: SpaceX - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Job listings content: application/json: schema: $ref: '#/components/schemas/PaginatedJobs' example: jobs: - id: '1899202395210649861' title: 'Engineer' url: 'https://x.com/i/jobs/1899202395210649861' applyUrl: 'https://xquik.com/example' location: 'United States' formattedSalary: 'Starting at $225K' salaryMin: 225000 salaryCurrencyCode: 'USD' salaryInterval: 'annually' account: id: '1812126202804711425' username: 'commonwarexyz' name: 'commonware' verified: true verifiedType: 'Business' has_next_page: true next_cursor: 'DAACCgACGRElMJcAAA' '400': description: > Missing query returns missing_query. An unknown filter value returns invalid_job_filter & names the values the filter takes. A cursor X cannot read, or one past its maxLength, returns invalid_cursor. Start again without it. All are free. content: application/json: schema: *error-schema examples: invalid_job_filter: value: error: 'invalid_job_filter' message: 'Unknown locationType "moon". Use onsite, remote or hybrid.' invalid_cursor: value: error: 'invalid_cursor' message: 'Cursor invalid or expired. Start again without cursor, then use next_cursor.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': { $ref: '#/components/responses/XApiError' } '429': *rate-limit-exceeded-response-2 '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' /x/jobs/locations: get: operationId: getJobLocations summary: Find job search locations by name description: > Returns the places whose names match a query, each with the location ID that GET /x/jobs/search takes. No match returns an empty list, free. tags: - Jobs security: *read-auth parameters: - name: q in: query required: true schema: { type: string } description: 'Place name or its start, such as new york. Its alias is query.' example: new york - name: limit in: query schema: type: integer minimum: 1 description: > Most places to return. Without it, every match returns. Its aliases are pageSize, count, max_results, maxItems, max_items & per_page. example: 5 - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Matching places content: application/json: schema: $ref: '#/components/schemas/JobLocations' example: locations: - id: '1720462281849397612' name: 'New York, US' - id: '1720462281920696805' name: 'New York City, NY' count: 2 '400': description: Missing place name content: application/json: schema: *error-schema example: error: 'missing_query' message: 'Search query required. Use q.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': { $ref: '#/components/responses/XApiError' } '429': *rate-limit-exceeded-response-2 '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' /x/jobs/{id}: get: operationId: getJob summary: Get an X job listing with its full description description: > Returns a public job listing with its description as text & Markdown, work type, seniority, salary, company & apply link. A job that closed returns job_not_found & is free. tags: - Jobs security: *read-auth parameters: - name: id in: path required: true schema: { type: string, maxLength: 2048 } description: > Job ID or URL-encoded job URL, such as x.com/i/jobs/123. Anything else gets 400 `invalid_job_id`. example: '1899202395210649861' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Job listing content: application/json: schema: type: object required: [job] properties: job: $ref: '#/components/schemas/Job' example: job: id: '1899202395210649861' title: 'Engineer' url: 'https://x.com/i/jobs/1899202395210649861' applyUrl: 'https://xquik.com/example' location: 'United States' locationType: 'remote' employmentType: 'full_time' seniorityLevel: 'lead' jobFunction: 'software_engineering' formattedSalary: 'Starting at $225K' salaryMin: 225000 salaryCurrencyCode: 'USD' salaryInterval: 'annually' featured: true shortDescription: 'Commonware is hiring founding engineers.' description: 'What is Commonware? We build open primitives.' descriptionMarkdown: '# What is Commonware?' account: id: '1812126202804711425' username: 'commonwarexyz' name: 'commonware' verified: true verifiedType: 'Business' '400': description: Invalid job ID, or one past its maxLength content: application/json: schema: *error-schema example: error: 'invalid_job_id' message: 'Send a job ID or job URL, such as x.com/i/jobs/123.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': description: Job not found content: application/json: schema: *error-schema example: error: 'job_not_found' message: 'Job not found. Check the job ID or x.com/i/jobs URL.' '424': { $ref: '#/components/responses/XApiError' } '429': { $ref: '#/components/responses/RateLimitExceeded' } '502': { $ref: '#/components/responses/XApiError' } '503': { $ref: '#/components/responses/ReadBusy' } /x/lists/search: get: operationId: searchLists summary: Search public X Lists by keyword description: Returns 1 page of public Lists with member counts, banners & owner profiles. X may rank the Lists differently per request. Pass next_cursor as cursor for the next page. tags: - Lists security: *read-auth parameters: - name: q in: query required: true schema: type: string description: Keywords to find Lists by, such as a topic. Alias query. - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Lists that match the keywords content: application/json: schema: $ref: '#/components/schemas/PaginatedLists' '400': description: > No keywords. Send them in q. A cursor past its maxLength returns invalid_cursor. content: application/json: schema: *error-schema example: error: 'missing_query' message: 'Search query required. Use q.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/lists/{id}: get: operationId: getList summary: Get an X List's name, description, counts and owner description: Returns 1 public X List as its page on X shows it. Accepts the List ID or the URL-encoded List URL, such as x.com/i/lists/4143408. A private List answers 404 list_not_found. tags: - Lists security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/ListPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List details content: application/json: schema: type: object required: [list] properties: list: $ref: '#/components/schemas/XList' example: list: id: '4143408' name: 'NASA Centers' description: 'NASA has 10 centers' memberCount: 11 subscriberCount: 859 owner: id: '11348282' username: 'NASA' name: 'NASA' url: 'https://x.com/i/lists/4143408' createdAt: '2009-12-02T22:41:02.000Z' bannerUrl: 'https://pbs.twimg.com/media/example.png' membersContext: '11 members' '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/lists/{id}/followers: get: operationId: getListFollowers description: Returns a public List's followers with resumable or standard pagination. A private List answers 404 list_not_found. summary: List followers of an X List tags: - Lists security: *read-auth parameters: &list-profile-coverage-parameters - $ref: '#/components/parameters/ListPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/AutomaticCoverageMode' - $ref: '#/components/parameters/LegacyCursorAlias' - $ref: '#/components/parameters/AutomaticFollowerPageSize' - $ref: '#/components/parameters/UserListMaxScan' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List profiles headers: *deprecated-read-headers content: &user-list-content application/json: schema: $ref: '#/components/schemas/UserListResult' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/lists/{id}/members: get: operationId: getListMembers description: Returns a public List's members with resumable or standard pagination. A private List answers 404 list_not_found. summary: List members of an X List tags: - Lists security: *read-auth parameters: *list-profile-coverage-parameters responses: '200': description: List members headers: *deprecated-read-headers content: *user-list-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/lists/{id}/tweets: get: operationId: getListTweets summary: List tweets from an X List description: > Omit mode for resumable maximum coverage. Pass next_cursor unchanged. Standard keeps legacy pagination. A private List answers 404 list_not_found. tags: - Lists security: *read-auth parameters: - $ref: '#/components/parameters/ListPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/LegacyCursorAlias' - $ref: '#/components/parameters/AutomaticCoverageMode' - $ref: '#/components/parameters/AutomaticTweetPageSize' - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/TweetIncludeReplies' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/CardName' - $ref: '#/components/parameters/Source' - $ref: '#/components/parameters/ExcludeSource' - $ref: '#/components/parameters/Geocode' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/Near' - $ref: '#/components/parameters/Within' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/Safe' - $ref: '#/components/parameters/News' - $ref: '#/components/parameters/Keywords' - $ref: '#/components/parameters/Place' - $ref: '#/components/parameters/PlaceCountry' - $ref: '#/components/parameters/PointRadius' - $ref: '#/components/parameters/BoundingBox' - $ref: '#/components/parameters/AdvancedQuery' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List tweets headers: *deprecated-read-headers content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/broadcasts/{id}: get: operationId: getBroadcast summary: Get an X broadcast's title, state, times, watch counts and host description: Returns 1 X broadcast, the live video X hosts at x.com/i/broadcasts, live or ended. Accepts the broadcast ID or the URL-encoded broadcast URL. Reading a broadcast adds no view to it. tags: - Broadcasts security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/BroadcastPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Broadcast details content: application/json: schema: type: object required: [broadcast] properties: broadcast: $ref: '#/components/schemas/Broadcast' example: broadcast: id: '1nGeLMWbkpaKX' title: 'USSF-259 Mission' state: 'Ended' startedAt: '2026-09-17T00:54:56.506Z' endedAt: '2026-09-17T01:17:35.036Z' totalWatched: 161758 totalWatching: 21639 width: 3840 height: 2160 creator: id: '34743251' username: 'SpaceX' name: 'SpaceX' '400': description: The path names no broadcast or runs past its maxLength content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'invalid_broadcast_id' message: 'Send a broadcast ID or URL, such as x.com/i/broadcasts/1nGeLMWbkpaKX.' '401': $ref: '#/components/responses/Unauthenticated' '402': $ref: '#/components/responses/PaymentRequired' '404': description: X knows no such broadcast content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'broadcast_not_found' message: 'Broadcast not found. Check the broadcast ID or x.com/i/broadcasts URL.' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/community-notes/contributors/{alias}: get: operationId: getCommunityNotesContributor summary: Get a Community Notes contributor's note and rating counts description: Returns 1 Community Notes contributor by the alias X gives them. Includes note counts by rating, rating counts & the deleted notes count. Each lookup costs 1 credit. tags: - Community Notes security: *read-auth parameters: - $ref: '#/components/parameters/ContributorPathAlias' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Contributor profile content: application/json: schema: type: object required: [contributor] properties: contributor: $ref: '#/components/schemas/CommunityNotesContributor' example: contributor: &community-notes-contributor-example alias: 'ardent-beach-friarbird' deletedNotesCount: 0 isApiContributor: false isTopWriter: false notesCount: awaitingMoreRatings: 18 currentlyRatedHelpful: 1 currentlyRatedNotHelpful: 2 updatedAt: '2026-10-12T22:18:40.096Z' ratingsCount: awaitingMoreRatings: 703 ratedAfterDecision: 154 successful: helpfulCount: 27 notHelpfulCount: 22 total: 49 unsuccessful: helpfulCount: 15 notHelpfulCount: 4 updatedAt: '2026-10-12T22:50:13.228Z' '400': description: The path names no contributor or runs past its maxLength. Free. content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'invalid_contributor_alias' message: 'Send a Community Notes alias or its x.com/i/communitynotes/u URL.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': $ref: '#/components/responses/ContributorNotFound' '424': { $ref: '#/components/responses/XApiError' } '429': *rate-limit-exceeded-response-2 '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' /x/community-notes/contributors/{alias}/notes: get: operationId: listCommunityNotesContributorNotes summary: List the Community Notes a contributor wrote, with their posts description: > Returns a contributor's notes, newest first, each with the post it is on. Includes notes X has not rated helpful, which x.com shows under no post. Each note costs 1 credit. Follow next_cursor for more. tags: - Community Notes security: *read-auth parameters: &contributor-notes-parameters - $ref: '#/components/parameters/ContributorPathAlias' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/NotesPageSize' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Notes with their posts content: application/json: schema: $ref: '#/components/schemas/PaginatedCommunityNotes' example: notes: - id: '2026375778254868976' createdAt: '2026-02-24T19:16:48.435Z' language: 'en' classification: 'MisinformedOrPotentiallyMisleading' contributor: alias: 'ardent-beach-friarbird' notesCount: currentlyRatedHelpful: 1 currentlyRatedNotHelpful: 2 ratingsCount: successful: total: 49 unsuccessful: helpfulCount: 15 notHelpfulCount: 4 text: "Since this is a wall of text article and the headline doesn't say, this quick-to-read context is necessary:\n\nDiscord is STILL rolling out Age Verification methods, just delayed to the second half of 2026 per the very own article in this post.\n\nhttps://discord.com/blog/getting-global-age-assurance-right-what-we-got-wrong-and-whats-changing" entities: - fromIndex: 244 toIndex: 340 ref: type: 'TimelineUrl' url: 'https://t.co/7fJbcLrO1k' ratingStatus: 'CurrentlyRatedHelpful' helpfulTags: ['ImportantContext', 'Clear'] decidedBy: 'CoreModel (v1.1)' fullyVisibleModel: true abovePcrhThreshold: false appealStatus: 'NotAppealed' deleted: false isApiAuthor: false isMediaNote: false mediaNoteMatchCount: 0 isUrlNote: false isTranslatable: false timeToHelpfulFromNoteMs: 132890587 timeToHelpfulFromPostMs: 136815576 postId: '2026359315657805939' post: id: '2026359315657805939' text: "Getting Global Age Assurance Right: What We Got Wrong and What’s Changing. \n\nRead the update: https://t.co/h7aRGmN7xW" createdAt: 'Tue Feb 24 18:11:23 +0000 2026' retweetCount: 542 replyCount: 4197 likeCount: 3990 quoteCount: 1122 viewCount: 7038435 bookmarkCount: 1472 lang: 'en' url: 'https://x.com/discord/status/2026359315657805939' author: id: '3065618342' username: 'discord' name: 'Discord' verifiedType: 'Business' has_next_page: true next_cursor: '-1767098234260' '400': $ref: '#/components/responses/ContributorNotesInvalidInput' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': $ref: '#/components/responses/ContributorNotFound' '424': { $ref: '#/components/responses/XApiError' } '429': *rate-limit-exceeded-response-2 '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' /x/community-notes/contributors/{alias}/deleted-notes: get: operationId: listCommunityNotesContributorDeletedNotes summary: List the Community Notes a contributor deleted description: > Returns the notes a contributor deleted, newest first. X keeps each note's ID, times, rating & tags. A notice replaces its text & post. Each note costs 1 credit. A contributor who deleted none returns an empty list, free. tags: - Community Notes security: *read-auth parameters: *contributor-notes-parameters responses: '200': description: Deleted notes content: application/json: schema: $ref: '#/components/schemas/PaginatedCommunityNotes' example: notes: - id: '2078950499982696756' createdAt: '2026-07-19T21:09:58.885Z' ratingStatus: 'CurrentlyRatedNotHelpful' notHelpfulTags: ['MissingKeyPoints', 'Incorrect'] decidedBy: 'CoreModel (v1.1)' fullyVisibleModel: true abovePcrhThreshold: false appealStatus: 'NotAppealed' deleted: true tombstone: 'This note has been deleted' isApiAuthor: false isMediaNote: false mediaNoteMatchCount: 0 isUrlNote: false has_next_page: false next_cursor: '' '400': $ref: '#/components/responses/ContributorNotesInvalidInput' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': $ref: '#/components/responses/ContributorNotFound' '424': { $ref: '#/components/responses/XApiError' } '429': *rate-limit-exceeded-response-2 '502': { $ref: '#/components/responses/XApiError' } '503': $ref: '#/components/responses/ReadBusy' /x/spaces/search: get: operationId: searchSpaces summary: Search X Spaces by keyword, host or topic description: Returns public Spaces each once, as GET /x/spaces/{id} serves them. Latest & Top find the Spaces that matching posts share, live, scheduled or ended. Live & Upcoming read X's own Spaces search, in X's order. They find live or scheduled Spaces by the words in their titles. Costs 1 credit per Space. tags: - Spaces security: *read-auth parameters: - name: q in: query required: true schema: type: string minLength: 1 example: 'from:solana' description: > Words, hashtags or X search operators, such as from:solana. Latest & Top add filter:spaces. Live & Upcoming match title words only, without operators. Alias query. - name: queryType in: query schema: type: string enum: [Latest, Top, Live, Upcoming] default: Latest description: Latest finds Spaces in the newest posts. Top finds them in the most engaging posts. Live lists Spaces on air now. Upcoming lists scheduled ones, as X's Spaces search does. Any case works. Aliases result_type, sort_order, type, search_type, product, category & section. - $ref: '#/components/parameters/CollectionCursor' - name: pageSize in: query description: > For Latest & Top, the posts a page reads, 20 at a time (1-100, default 20). Posts often share the same Space, so a page returns fewer Spaces. Send 100 to read a search fastest. For Live & Upcoming, the most Spaces a page returns. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 100 default: 20 - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Spaces found content: application/json: schema: type: object required: [spaces, has_next_page, next_cursor] properties: spaces: type: array description: Public Spaces, each once. Latest & Top list them in the order the posts share them. Live & Upcoming keep X's order. items: $ref: '#/components/schemas/Space' example: - id: '1OGwblLjnQMKB' title: 'Extending the Network to the Edge' state: 'Ended' admins: [] speakers: [] listeners: [] has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' example: spaces: - id: '1OGwblLjnQMKB' title: 'Extending the Network to the Edge' state: 'Ended' startedAt: '2026-03-11T17:00:26.227Z' endedAt: '2026-03-11T17:49:29.190Z' totalLiveListeners: 841 totalReplayWatched: 609 admins: - id: '951329744804392960' username: 'solana' name: 'Solana' speakers: [] listeners: [] has_next_page: true next_cursor: 'DAACCgACGRElMJcAAA' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/spaces/{id}: get: operationId: getSpace summary: Get an X Space's title, state, times, audience, host and speakers description: Returns 1 X Space as X shows it, live, scheduled or ended. Accepts the Space ID or the URL-encoded Space URL. A Space X limits to subscribers or a community answers 404. tags: - Spaces security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/SpacePathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Space details content: application/json: schema: type: object required: [space] properties: space: $ref: '#/components/schemas/Space' example: space: id: '1OGwblLjnQMKB' title: 'Extending the Network to the Edge' state: 'Ended' startedAt: '2026-03-11T17:00:26.227Z' endedAt: '2026-03-11T17:49:29.190Z' totalLiveListeners: 841 totalReplayWatched: 609 creator: id: '951329744804392960' username: 'solana' name: 'Solana' admins: - id: '951329744804392960' username: 'solana' name: 'Solana' speakers: [] listeners: [] '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *not-found-response '424': $ref: '#/components/responses/XApiError' '429': *rate-limit-exceeded-response-2 '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/spaces/{id}/replay: get: operationId: getSpaceReplay summary: Get an ended X Space's replay as an HLS playback URL description: Returns the recording X plays back once a Space is over, in state Ended or TimedOut. Accepts the Space ID or the URL-encoded Space URL. Check state and isAvailableForReplay with the Space lookup first. A live or scheduled Space answers 409, and a cancelled one 404. tags: - Spaces security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/SpacePathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Space replay content: application/json: schema: type: object required: [replay] properties: replay: type: object description: Recording of an ended Space required: [url] properties: url: type: string format: uri description: HLS playlist of the recording example: 'https://prod-fastly-us-east-1.video.pscp.tv/Transcoding/v1/hls/example/audio-space/playlist.m3u8?type=replay' streamType: type: string description: Stream format, as X names it example: 'HLS' status: type: string description: Stream status, as X names it example: 'LIVE_PUBLIC' example: replay: url: 'https://prod-fastly-us-east-1.video.pscp.tv/Transcoding/v1/hls/example/audio-space/playlist.m3u8?type=replay' streamType: 'HLS' status: 'LIVE_PUBLIC' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/Unauthenticated' '402': $ref: '#/components/responses/PaymentRequired' '404': description: Unknown Space, a Space without a recording, or a cancelled Space content: application/json: schema: $ref: '#/components/schemas/Error' examples: unknownSpace: summary: X does not know the Space value: error: 'not_found' message: 'Resource not found.' noReplay: summary: The host kept no recording value: error: 'replay_unavailable' message: 'This Space has no replay. Its host kept no recording.' canceled: summary: The Space was cancelled before it started value: error: 'space_canceled' message: 'This Space was canceled before it started. It has no replay.' '409': description: The Space has not ended content: application/json: schema: $ref: '#/components/schemas/Error' example: error: 'space_not_ended' message: 'This Space has not ended. Its replay is ready after it ends.' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/tweets/{id}/quotes: get: operationId: getTweetQuotes description: >- Returns public posts quoting the tweet, newest first, replies included. Drop them with replies=exclude. Send queryType=Top for the quotes X ranks highest. summary: List quote tweets of a tweet tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/LegacyPaginationMode' - $ref: '#/components/parameters/AutomaticTweetPageSize' - name: includeReplies in: query schema: { type: boolean } description: > Keep replies that quote the post. Automatic pages keep them unless this is false. Standard pages keep them only when it is true. Explicit replies takes precedence. - name: queryType in: query schema: { type: string, enum: [Latest, Top], default: Latest } description: > Latest for newest first, or Top for the quotes X ranks highest. Top is X's ranking, not a count order, & a later page can hold a quote X ranks higher. Any case works. Alias sort, which also takes Recency & Relevance. Send the same value with each cursor. Standard pages list Latest. - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/CardName' - $ref: '#/components/parameters/Source' - $ref: '#/components/parameters/ExcludeSource' - $ref: '#/components/parameters/Geocode' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/Near' - $ref: '#/components/parameters/Within' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/Safe' - $ref: '#/components/parameters/News' - $ref: '#/components/parameters/Keywords' - $ref: '#/components/parameters/ListId' - $ref: '#/components/parameters/Place' - $ref: '#/components/parameters/PlaceCountry' - $ref: '#/components/parameters/PointRadius' - $ref: '#/components/parameters/BoundingBox' - $ref: '#/components/parameters/AdvancedQuery' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of quote tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/tweets/{id}/replies: get: operationId: getTweetReplies x-mcp-return-body-statuses: [404, 424] summary: List replies to a tweet description: > Returns direct replies with automatic maximum coverage and pagination. A retweet ID returns replies to the original post. Complete mode adds nested replies, diagnostics, and a 424 below 80% coverage. A fully read time window returns 200. So does a post that shows none of the replies it counts, with hiddenReplies. It reads replies without a search, so q or query answers 400 before any read or charge. To search a post's replies, call GET /x/tweets/search with q=conversation_id:{id}. tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/LegacyCursorAlias' - name: mode in: query schema: type: string enum: [standard, complete] description: > Override automatic coverage. Standard uses legacy pagination. Complete adds nested replies, diagnostics, scope, depth, and original-post controls. - name: limit in: query schema: &positive-integer type: integer minimum: 1 description: > Complete mode defaults to 25,000 combined direct & nested replies. Set another total with limit. Automatic pages accept 1-300, standard pages 1-100. - $ref: '#/components/parameters/AutomaticTweetPageSize' - name: scope in: query schema: type: string enum: [all, direct, nested] default: all description: Select all replies, direct replies, or nested replies. - name: maxDepth in: query schema: *positive-integer description: Maximum reply depth from the source post. - name: sort in: query schema: type: string enum: [relevance, latest, oldest, likes] description: > Sorts the selected replies before limit applies. Complete mode defaults to relevance. Automatic pages list the newest first unless you set sort. Standard pages ignore it. With likes, each page is sorted by likes. A later page can hold a reply with more likes. The order is final on the last page. Latest & oldest sort every row by date. They read the whole thread first, for up to 20 s. An answer that stopped before every reply X shows sets orderPartial. - name: excludeOriginalAuthor in: query schema: { type: boolean, default: false } description: Exclude replies written by the source-post author. - name: includeOriginalPost in: query schema: { type: boolean, default: false } description: Include the source post and count it toward limit. - name: includeHidden in: query schema: { type: boolean, default: false } description: > Complete mode only. Adds the replies the post's author hid, each with hiddenByAuthor true. They count toward limit like any reply. A paged read answers 400. Get its hidden replies from GET /x/tweets/{id}/hidden-replies. - name: hasMediaOnly in: query schema: { type: boolean, default: false } description: Only return replies containing media. - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of replies headers: *deprecated-read-headers content: application/json: schema: $ref: '#/components/schemas/TweetReplies' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/RepliesIncomplete' '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/tweets/{id}/retweeters/check: parameters: - $ref: '#/components/parameters/TweetPathId' get: operationId: getTweetRepostCheck description: Returns whether 1 account reposted the post, read from its newest posts. A repost older than the posts read returns false with complete false. Each check costs 1 credit. summary: Check whether a user retweeted a tweet tags: - Tweets security: *read-auth parameters: - name: user in: query required: true schema: type: string maxLength: 2048 example: 'nasa' description: User ID, username with or without @, or profile URL. - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Repost check result content: application/json: schema: type: object required: [ isRetweeted, retweetedAt, retweetId, tweetId, userId, checkedPosts, complete, ] properties: isRetweeted: type: boolean description: Whether the account reposted the post. example: true retweetedAt: type: [string, 'null'] format: date-time description: When the account reposted it, else null. example: '2026-09-11T16:59:50.000Z' retweetId: type: [string, 'null'] description: The ID of the account's repost, else null. example: '2098456494362460375' tweetId: type: string example: '2098439298617856319' userId: type: string example: '3065618342' checkedPosts: type: integer minimum: 0 description: How many of the account's newest posts the check read. example: 20 complete: type: boolean description: Whether the check read the account's whole timeline. example: false example: isRetweeted: true retweetedAt: '2026-09-11T16:59:50.000Z' retweetId: '2098456494362460375' tweetId: '2098439298617856319' userId: '3065618342' checkedPosts: 20 complete: false '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '404': $ref: '#/components/responses/UserNotFound' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': $ref: '#/components/responses/RateLimitExceeded' '424': $ref: '#/components/responses/XApiError' /x/tweets/{id}/retweeters: get: operationId: getTweetRetweeters description: Returns a post's reposters. includeRetweetTimestamp adds retweeted_at in Unix seconds. Null means the lookup failed or the newest profile page has no matching repost. The created field is the account's creation time. Timestamp lookups make the request slower. summary: List users who retweeted a tweet tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/CollectionCursor' - name: includeRetweetTimestamp in: query description: Look up repost event times. schema: *boolean-default-false - $ref: '#/components/parameters/FollowerPageSize' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/EnrichProfiles' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of retweeters headers: *user-list-headers content: *paginated-users-content '400': description: > Invalid input returns invalid_input. A cursor X cannot read, or one past its maxLength, returns invalid_cursor. Start again without it. Both are free. content: application/json: schema: *error-schema examples: invalid_input: value: error: 'invalid_input' message: 'Invalid input. Check the request body.' invalid_cursor: value: error: 'invalid_cursor' message: 'Cursor invalid or expired. Start again without cursor, then use next_cursor.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/retweeter-ids: get: operationId: getTweetRetweeterIds description: Returns the user IDs of a post's reposters, in the order & pages of /x/tweets/{id}/retweeters. Use it when you need IDs only. Each ID costs 1 credit. A post nobody reposted returns an empty list for free. summary: List the user IDs of users who retweeted a tweet tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/FollowerPageSize' responses: '200': description: A page of reposter IDs content: application/json: schema: $ref: '#/components/schemas/PaginatedUserIds' '400': description: > A post ID that is not a number returns invalid_tweet_id. A cursor X cannot read, or one past its maxLength, returns invalid_cursor. Start again without it. Neither costs a credit. content: application/json: schema: *error-schema examples: invalid_tweet_id: value: error: 'invalid_tweet_id' message: 'Send a tweet ID or tweet URL, such as x.com/nasa/status/20.' invalid_cursor: value: error: 'invalid_cursor' message: 'Cursor invalid or expired. Start again without cursor, then use next_cursor.' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/hidden-replies: parameters: - $ref: '#/components/parameters/TweetPathId' get: operationId: getTweetHiddenReplies description: Returns the replies the post's author hid, oldest first, with the replies to them. A post without hidden replies returns an empty list. summary: List the replies a tweet's author hid tags: - Tweets security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: Hidden replies content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/thread: parameters: - $ref: '#/components/parameters/TweetPathId' get: operationId: getTweetThread description: Returns visible posts from the selected conversation thread. Results exclude X ads. summary: Get full conversation thread for a tweet tags: - Tweets security: *read-auth parameters: *tweet-row-page-parameters responses: '200': description: Thread tweets content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/translation: get: operationId: translateTweet description: Returns X's own translation of 1 public tweet into the language you pick, with the links, mentions, and tags X places in the translated text. summary: Translate a tweet into a chosen language tags: - Tweets security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/TweetPathId' - name: language in: query required: true description: Language code to translate into, such as `en`, `tr`, `pt-br`, or `zh-tw`. Upper and lower case both work. schema: type: string maxLength: 12 example: tr - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Translated tweet text content: application/json: schema: type: object required: [translation] properties: translation: $ref: '#/components/schemas/TweetTranslation' example: translation: tweetId: '2102882545427714266' language: tr sourceLanguage: en text: 'Artemis Anlaşmaları’na Hoş Geldiniz, Hırvatistan https://t.co/Xe1nm2pkSX' entities: urls: - url: 'https://t.co/Xe1nm2pkSX' expanded_url: 'https://go.nasa.gov/3VcvAQn' display_url: go.nasa.gov/3VcvAQn indices: [49, 72] '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/translation: get: operationId: translateUserBio description: Returns X's own translation of 1 profile's bio into the language you pick, with the links, mentions, and tags X places in the translated text. A profile without a bio returns translation null & a message, free of charge. summary: Translate a user's bio into a chosen language tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - name: language in: query required: true description: Language code to translate into, such as `es`, `tr`, `pt-br`, or `zh-tw`. Upper and lower case both work. schema: type: string example: es - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Translated bio content: application/json: schema: type: object required: [translation] properties: translation: anyOf: - $ref: '#/components/schemas/ProfileTranslation' - type: 'null' description: Null when the profile has no bio. example: userId: '11348282' userName: NASA language: es sourceLanguage: en text: 'Haciendo lo aparentemente imposible, posible. ✨' entities: {} message: type: string description: Says why translation is null. example: This profile has no bio to translate. example: translation: userId: '11348282' userName: NASA language: es sourceLanguage: en text: 'Haciendo lo aparentemente imposible, posible. ✨' entities: {} '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/insights: get: operationId: getUserInsights description: > Returns engagement insights for 1 profile. They are engagement rate, averages per post and posting rate, from its counts and its last 20 posts. Reposts and the pinned post stay out of the averages. Each report costs 1 credit, whatever it reads. summary: Get a user's engagement rate and averages tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Profile insights content: application/json: schema: type: object required: [insights] properties: insights: $ref: '#/components/schemas/UserInsights' message: type: string description: Says why the report has counts only. Sent only when postsPrivate is true. example: >- This account's posts are private, so the report has its counts only. example: insights: &user-insights-example userId: '11348282' userName: NASA followers: 92376187 following: 115 posts: 74336 accountAgeDays: 6858 postsPrivate: false sample: posts: 10 oldestAt: '2026-09-23T13:15:28.000Z' newestAt: '2026-09-28T22:12:05.000Z' averages: likes: 3684.2 replies: 142.7 reposts: 459.8 quotes: 45 bookmarks: 209.7 views: 785247.8 engagements: 4331.7 engagementRate: 0.0047 engagementPerView: 0.5516 postsPerDay: 1.6814 topPostId: '2102761519985332442' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/insights: get: operationId: getTweetInsights description: > Returns engagement insights for 1 tweet. They are engagements per hour since it went up, per view and per follower of its author, and how far it spread. Each report costs 1 credit, whatever it reads. summary: Get a tweet's engagement rate and velocity tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Tweet insights content: application/json: schema: type: object required: [insights] properties: insights: $ref: '#/components/schemas/TweetInsights' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/live: get: operationId: getUserLiveStatus description: Says whether 1 user is broadcasting live video on X right now, with their latest broadcast, live or ended. Each check costs 1 credit. summary: Check whether a user is live on X now tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Live status content: application/json: schema: $ref: '#/components/schemas/UserLiveStatus' example: live: false userId: '11348282' userName: NASA broadcast: id: '1DxLdZyVPMMxm' title: "NASA's SpaceX Crew-12 Re-Entry & Splashdown" state: 'Ended' startedAt: '2026-10-08T14:20:33.863Z' endedAt: '2026-10-08T16:38:16.770Z' totalWatched: 220908 totalWatching: 119617 width: 3840 height: 2160 '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/tweets/{id}/embed: get: operationId: getTweetEmbed description: Returns the HTML that X gives websites to embed 1 public tweet, with the tweet's link and author. summary: Get embed HTML for a tweet tags: - Tweets security: *read-auth x-payment-info: offers: - amount: '150' currency: *tempo-usd intent: charge method: tempo parameters: - $ref: '#/components/parameters/TweetPathId' - name: theme in: query description: Color theme of the embed. X uses light when left out. schema: type: string enum: [light, dark] - name: hideMedia in: query description: Set `true` to leave photos, videos, and link cards out. schema: type: boolean - name: hideThread in: query description: Set `true` to leave the tweet this one replies to out. schema: type: boolean - name: omitScript in: query description: Set `true` to leave the widget script tag out, for pages that load it once themselves. schema: type: boolean - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Embed HTML content: application/json: schema: type: object required: [embed] properties: embed: $ref: '#/components/schemas/TweetEmbed' example: embed: tweetId: '2102882545427714266' url: 'https://x.com/NASA/status/2102882545427714266' authorName: NASA authorUrl: 'https://x.com/NASA' html: '' width: 550 '400': *invalid-input-response '401': *unauthenticated-response '402': *payment-required-response '404': *tweet-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/links/resolve: get: operationId: resolveLinks description: Returns where each t.co link leads, as X's own redirect says. Xquik reads the redirect and never visits the target site. A link t.co does not have comes back without `resolvedUrl` and costs nothing. A link X does not answer for in time comes back in `unprocessedUrls`, free. Each resolved link costs 1 credit. summary: Resolve t.co links to their target URLs tags: - Tweets security: *read-auth parameters: - name: urls in: query required: true description: 1 to 100 links of the form `https://t.co/Xe1nm2pkSX`, separated by commas. Any other link is refused. A link sent twice counts once. A longer URL fails at the edge before Xquik reads it. schema: type: string maxLength: 13078 example: 'https://t.co/Xe1nm2pkSX' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Resolved links in the order sent content: application/json: schema: type: object required: [links, unprocessedUrls] properties: links: type: array items: $ref: '#/components/schemas/ResolvedLink' example: - url: 'https://t.co/Xe1nm2pkSX' resolvedUrl: 'https://go.nasa.gov/3VcvAQn' unprocessedUrls: type: array description: Links not read, in the order sent. X did not answer for them in time, or available credits ran out. Send them again. items: type: string example: 'https://t.co/QQGjcE6KKq' example: [] example: links: - url: 'https://t.co/Xe1nm2pkSX' resolvedUrl: 'https://go.nasa.gov/3VcvAQn' unprocessedUrls: [] '400': $ref: '#/components/responses/InvalidInput' '401': *anonymous-guest-authentication-response '402': *payment-required-response '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/XApiError' /x/tweets/{id}/subtitles: get: operationId: getTweetSubtitles description: Returns the caption tracks of 1 public tweet's videos, as X's player reads them. Each track has its language, name, timed cues, and full text. A tweet without video, or a video without captions, returns no track and costs nothing. summary: Get video subtitles and captions for a tweet tags: - Tweets security: *read-auth parameters: - $ref: '#/components/parameters/TweetPathId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: Caption tracks of the tweet's videos content: application/json: schema: type: object required: [subtitles] properties: subtitles: $ref: '#/components/schemas/TweetSubtitles' example: subtitles: tweetId: '2104593672624886205' tracks: - mediaKey: '13_2104593621043314689' language: en name: Planetary Defenders_Caption.en_US.srt autoGenerated: false url: 'https://video.twimg.com/subtitles/amplify_video/2104593621043314689/0/-FdxBBY2iGcoP5wb.vtt' text: This asteroid 2024 YR4 might get interesting. truncated: false cues: - startMs: 0 endMs: 3370 text: |- This asteroid 2024 YR4 might get interesting. '400': $ref: '#/components/responses/InvalidInput' '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *tweet-not-found-response '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': $ref: '#/components/responses/XApiError' /x/users/{id}/follower-ids: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserFollowerIds description: Returns the user IDs of the selected user's followers, newest first, up to 5,000 a page. Use it when you need IDs only. Each ID costs 1 credit. summary: List the user IDs of a user's followers tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/UserIdPageSize' responses: '200': description: A page of follower IDs content: &user-id-page-content application/json: schema: $ref: '#/components/schemas/PaginatedUserIds' '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedFollowerList' '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/following-ids: parameters: - $ref: '#/components/parameters/UserPathId' get: operationId: getUserFollowingIds description: Returns the user IDs of the accounts the selected user follows, newest first, up to 5,000 a page. Use it when you need IDs only. Each ID costs 1 credit. summary: List the user IDs of the accounts a user follows tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/UserIdPageSize' responses: '200': description: A page of following IDs content: *user-id-page-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedFollowingList' '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/followers: get: operationId: getUserFollowers description: Returns public follower profiles for the selected user, newest first. x.com puts some promoted followers first. Xquik doesn't. summary: List followers of a user tags: - Users security: *read-auth parameters: &user-profile-coverage-parameters - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/AutomaticCoverageCursor' - $ref: '#/components/parameters/AutomaticCoverageMode' - $ref: '#/components/parameters/LegacyCursorAlias' - $ref: '#/components/parameters/AutomaticFollowerPageSize' - $ref: '#/components/parameters/UserListMaxScan' - $ref: '#/components/parameters/UserMinFollowers' - $ref: '#/components/parameters/UserMaxFollowers' - $ref: '#/components/parameters/UserMinFollowing' - $ref: '#/components/parameters/UserMaxFollowing' - $ref: '#/components/parameters/UserMinStatuses' - $ref: '#/components/parameters/UserMaxStatuses' - $ref: '#/components/parameters/UserMinAccountAgeDays' - $ref: '#/components/parameters/UserVerifiedOnly' - $ref: '#/components/parameters/UserBlueVerifiedOnly' - $ref: '#/components/parameters/UserVerifiedType' - $ref: '#/components/parameters/UserHasWebsite' - $ref: '#/components/parameters/UserHasLocation' - $ref: '#/components/parameters/UserHasEmail' - $ref: '#/components/parameters/UserBusinessEmailOnly' - $ref: '#/components/parameters/UserEmailDomains' - $ref: '#/components/parameters/UserBioContains' - $ref: '#/components/parameters/UserLocationContains' - $ref: '#/components/parameters/UserUsernameContains' - $ref: '#/components/parameters/EnrichProfiles' - $ref: '#/components/parameters/LegacyFollowerLimit' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of user followers headers: &deprecated-user-list-headers X-Xquik-Profile-Enrichment: $ref: '#/components/headers/ProfileEnrichment' X-Xquik-Credits-Charged: $ref: '#/components/headers/CreditsCharged' Deprecation: { $ref: '#/components/headers/Deprecation' } Link: { $ref: '#/components/headers/DeprecationLink' } content: *user-list-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedFollowerList' '404': *user-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/users/{id}/following: get: operationId: getUserFollowing description: Returns public profiles followed by the selected user. summary: List accounts a user follows tags: - Users security: *read-auth parameters: *user-profile-coverage-parameters responses: '200': description: List of following headers: *deprecated-user-list-headers content: *user-list-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedFollowingList' '404': *user-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/users/{id}/mentions: get: operationId: getUserMentions description: Returns public posts mentioning the selected user. summary: List tweets mentioning a user tags: - Users security: *read-auth parameters: - $ref: '#/components/parameters/UserPathId' - $ref: '#/components/parameters/CollectionCursor' - $ref: '#/components/parameters/ResultPageSize' - $ref: '#/components/parameters/TweetSinceTime' - $ref: '#/components/parameters/TweetUntilTime' - $ref: '#/components/parameters/FromUser' - $ref: '#/components/parameters/ToUser' - $ref: '#/components/parameters/Mentioning' - $ref: '#/components/parameters/Language' - $ref: '#/components/parameters/SinceDate' - $ref: '#/components/parameters/UntilDate' - $ref: '#/components/parameters/MediaType' - $ref: '#/components/parameters/MinLikes' - $ref: '#/components/parameters/MinRetweets' - $ref: '#/components/parameters/MinReplies' - $ref: '#/components/parameters/MinQuotes' - $ref: '#/components/parameters/MinViews' - $ref: '#/components/parameters/MinBookmarks' - $ref: '#/components/parameters/MaxFaves' - $ref: '#/components/parameters/MaxRetweets' - $ref: '#/components/parameters/MaxReplies' - $ref: '#/components/parameters/MaxQuotes' - $ref: '#/components/parameters/BlueVerifiedOnly' - $ref: '#/components/parameters/SinceId' - $ref: '#/components/parameters/MaxId' - $ref: '#/components/parameters/WithinTime' - $ref: '#/components/parameters/NativeRetweets' - $ref: '#/components/parameters/VerifiedOnly' - $ref: '#/components/parameters/Replies' - $ref: '#/components/parameters/Retweets' - $ref: '#/components/parameters/Quotes' - $ref: '#/components/parameters/ExactPhrase' - $ref: '#/components/parameters/ExcludeWords' - $ref: '#/components/parameters/AnyWords' - $ref: '#/components/parameters/Hashtags' - $ref: '#/components/parameters/Cashtags' - $ref: '#/components/parameters/Url' - $ref: '#/components/parameters/ConversationId' - $ref: '#/components/parameters/InReplyToTweetId' - $ref: '#/components/parameters/QuotesOfTweetId' - $ref: '#/components/parameters/RetweetsOfTweetId' - $ref: '#/components/parameters/Fields' - $ref: '#/components/parameters/Omit' responses: '200': description: List of mentions content: *paginated-tweets-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '404': *user-not-found-response '502': *x-api-error-response '503': $ref: '#/components/responses/ReadBusy' '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response /x/users/{id}/verified-followers: get: operationId: getUserVerifiedFollowers description: Returns verified public profiles following the selected user. summary: List verified followers of a user tags: - Users security: *read-auth parameters: *user-profile-coverage-parameters responses: '200': description: List of verified followers headers: *deprecated-user-list-headers content: *user-list-content '400': *invalid-input-response '401': *anonymous-guest-authentication-response '402': *payment-required-response '403': $ref: '#/components/responses/ProtectedVerifiedFollowerList' '404': *user-not-found-response '502': *x-api-error-response '429': *rate-limit-exceeded-response-2 '424': *x-api-error-response '409': $ref: '#/components/responses/CoverageCursorUnavailable' '410': $ref: '#/components/responses/CursorGone' '503': $ref: '#/components/responses/MaximumCoverageBusy' /x/analysis/sentiment: post: operationId: analyzeTweetSentiment x-mcp-annotations: { readOnlyHint: true } summary: Analyze the sentiment of posts with AI description: Answers each post's attitude, its intensity & its sarcasm probability. Send post IDs, an X search, an account, a List, a post's replies or quotes, or your own texts. Each analyzed post costs 2 credits. A post without an analysis costs nothing. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts whose sentiment to analyze, as tweetIds, texts or a search such as query or username, with optional analysis settings. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: &analysis-search-example summary: 'A search, newest posts first' value: query: 'Artemis lang:en' queryType: 'Latest' sinceTime: '2026-09-01T00:00:00Z' untilTime: '2026-09-30T23:59:59Z' limit: 20 nextPage: &analysis-nextPage-example summary: 'The next page of a search' value: query: 'Artemis lang:en' cursor: 'xqcv1_tkGoEx1UJRqeog9a2BJdmzUZTMCoU_M8kb' limit: 20 account: &analysis-account-example summary: "1 account's posts" value: username: '@NASA' limit: 20 list: &analysis-list-example summary: "A List's posts" value: listId: '4143408' limit: 20 quotes: &analysis-quotes-example summary: 'Quotes of a post' value: quotesOf: '2102882545427714266' limit: 20 replies: &analysis-replies-example summary: 'Replies to a post' value: repliesTo: '2102882545427714266' limit: 20 posts: &analysis-posts-example summary: 'Posts by ID or URL' value: tweetIds: - '2102882545427714266' - 'https://x.com/NASA/status/2102761519985332442' texts: &analysis-texts-example summary: 'Your own texts' value: texts: - 'We shipped dark mode today. Tell us what breaks.' - 'My headphones stopped charging after 2 days. Who can help?' baseline: &analysis-baseline-example summary: 'Compared with an earlier answer' value: tweetIds: - '2102882545427714266' baseline: - id: '2102882545427714266' answers: sentiment: 'positive' intensity: 1 own: summary: 'Your own context' value: query: 'Sony WH-1000XM6 lang:en' limit: 20 analysis: context: 'Consumer headphones & customer service.' responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/analysis/brand: post: operationId: analyzeBrandMentions x-mcp-annotations: { readOnlyHint: true } summary: Analyze brand mentions in posts with AI description: Answers whether each post is about your brand, the author's attitude toward it & the author's relationship with it. Name the brand in analysis.targets. Each analyzed post costs 2 credits. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts to check for brand mentions, as tweetIds, texts or a search such as query or username, with the brand in analysis.targets. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: *analysis-search-example nextPage: *analysis-nextPage-example account: *analysis-account-example list: *analysis-list-example quotes: *analysis-quotes-example replies: *analysis-replies-example posts: *analysis-posts-example texts: *analysis-texts-example baseline: *analysis-baseline-example own: summary: 'Your brand & its aliases' value: query: 'Sony WH-1000XM6 lang:en' limit: 20 analysis: targets: - name: 'Sony' aliases: - 'WH-1000XM6' responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/analysis/news: post: operationId: analyzeNewsPosts x-mcp-annotations: { readOnlyHint: true } summary: Classify news posts with AI description: Answers each post's format, such as reporting, commentary or speculation, its source attribution & its relevance to your topic. Name the topic in analysis.targets. Each analyzed post costs 2 credits. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts to classify as news, as tweetIds, texts or a search such as query or username, with the topic in analysis.targets. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: *analysis-search-example nextPage: *analysis-nextPage-example account: *analysis-account-example list: *analysis-list-example quotes: *analysis-quotes-example replies: *analysis-replies-example posts: *analysis-posts-example texts: *analysis-texts-example baseline: *analysis-baseline-example own: summary: 'The story you follow' value: query: 'Artemis lang:en' limit: 20 analysis: targets: - name: 'Artemis program' responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/analysis/market-signals: post: operationId: analyzeMarketSignals x-mcp-annotations: { readOnlyHint: true } summary: Read stock & crypto signals from posts with AI description: Answers each post's stance on an asset, its content type, its conviction & its relevance. The summary counts bullish & bearish posts per cashtag. Name the asset in analysis.targets. Each analyzed post costs 2 credits. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts to read market signals from, as tweetIds, texts or a search such as query or username, with the asset in analysis.targets. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: *analysis-search-example nextPage: *analysis-nextPage-example account: *analysis-account-example list: *analysis-list-example quotes: *analysis-quotes-example replies: *analysis-replies-example posts: *analysis-posts-example texts: *analysis-texts-example baseline: *analysis-baseline-example own: summary: 'The asset you follow' value: query: '$NVDA lang:en' limit: 20 analysis: targets: - name: 'NVIDIA' aliases: - '$NVDA' responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/analysis/viral-score: post: operationId: analyzeTweetViralScore x-mcp-annotations: { readOnlyHint: true } summary: Score how viral posts or drafts read with AI description: Answers each post's hook, clarity, payoff, humor, spam risk & likely reaction, & adds a Viral Score from 0 to 100 with a verdict. The score rates the wording. It does not predict likes or views. Send drafts in texts to score them before posting. Each analyzed post costs 2 credits. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts or drafts to score, as tweetIds, texts or a search such as query or username, with optional analysis settings. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: *analysis-search-example nextPage: *analysis-nextPage-example account: *analysis-account-example list: *analysis-list-example quotes: *analysis-quotes-example replies: *analysis-replies-example posts: *analysis-posts-example texts: *analysis-texts-example baseline: *analysis-baseline-example own: summary: 'Your own context' value: texts: - 'We shipped dark mode today. Tell us what breaks.' analysis: context: "A developer tool's launch posts." responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' /x/analysis/classify: post: operationId: classifyTweets x-mcp-annotations: { readOnlyHint: true } summary: Classify posts with your own AI questions description: Answers 1 to 8 questions you write in analysis.questions. A choice picks a category, such as a topic. A score picks a level. A probability answers yes or no. Without questions it answers the sentiment questions. Each analyzed post costs 2 credits. tags: [Analysis] security: [{ apiKey: [] }, { oauthBearer: [] }] requestBody: required: true description: Posts to classify, as tweetIds, texts or a search such as query or username, with your questions in analysis.questions. content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisRequest' examples: search: *analysis-search-example nextPage: *analysis-nextPage-example account: *analysis-account-example list: *analysis-list-example quotes: *analysis-quotes-example replies: *analysis-replies-example posts: *analysis-posts-example texts: *analysis-texts-example baseline: *analysis-baseline-example own: summary: 'Your own questions' value: texts: - 'My headphones stopped charging after 2 days. Who can help?' analysis: questions: - id: 'request' type: 'choice' version: '1' instructions: 'What does the author ask for?' categories: support: 'Help with a problem.' recommendation: 'Advice on choosing a product.' other: 'Neither request.' responses: '200': $ref: '#/components/responses/TweetAnalysisPage' '400': $ref: '#/components/responses/InvalidInput' '401': $ref: '#/components/responses/AnonymousGuestAuthenticationRequired' '402': $ref: '#/components/responses/PaymentRequired' '403': $ref: '#/components/responses/ProtectedTimeline' '424': $ref: '#/components/responses/XApiError' '429': $ref: '#/components/responses/RateLimitExceeded' '502': $ref: '#/components/responses/XApiError' '503': $ref: '#/components/responses/ReadBusy' components: securitySchemes: apiKey: type: apiKey in: header name: x-api-key description: >- Xquik API key passed through the x-api-key header. Xquik-Api-Key is a vendor-prefixed alias. API keys beginning with xq_ can also use `Authorization: Bearer`. oauthBearer: type: http scheme: bearer description: >- OAuth 2.1 access token passed through `Authorization: Bearer`. Values beginning with xq_ remain Xquik API-key credentials, not OAuth tokens. cookieSession: type: apiKey in: cookie name: __Host-xquik_session description: Secure Xquik browser session cookie. parameters: CollectionCursor: name: cursor in: query schema: { type: string, maxLength: 4096 } description: Pagination cursor for collection results. Also read as next_cursor, next_token, pagination_token or continuation_token. TweetPathId: name: id in: path required: true schema: { type: string, maxLength: 2048 } description: > Tweet ID or URL-encoded tweet URL, such as x.com/nasa/status/20. Takes x.com & twitter.com links with or without https://, www., mobile., a query or a fragment, & /i/status or /i/web/status links. Anything else gets 400 `invalid_tweet_id`. example: '2102882545427714266' UserPathId: name: id in: path required: true schema: { type: string, maxLength: 2048 } description: > User ID, username with or without @, or URL-encoded profile URL, such as x.com/nasa or x.com/i/user/11348282. A number is a user ID. Writes look up a username's ID before sending. Anything else gets 400 `invalid_user_id`. example: '11348282' DmUserPathId: name: userId in: path required: true schema: { type: string, maxLength: 2048 } description: > The other person in the conversation, as a user ID, username with or without @, or URL-encoded profile URL, such as x.com/nasa. Xquik looks up a username's ID first. Anything else gets 400 `invalid_user_id`. example: '44196397' DmMessagePathId: name: messageId in: path required: true schema: type: string maxLength: 19 pattern: '^[1-9][0-9]{0,18}$' description: DM ID from DM history. Another value gets 400 `invalid_message_id`. example: '1234567890123456789' CommunityPathId: name: id in: path required: true schema: type: string maxLength: 19 pattern: '^[1-9][0-9]{0,18}$' example: '1500000000000000000' description: X Community ID, a number up to 19 digits. Another value gets a free 400 `invalid_community_id` before X is read. CommunityWriteId: name: id in: path required: true schema: type: string maxLength: 19 pattern: '^[1-9][0-9]{0,18}$' example: '1500000000000000000' description: X Community ID, a number up to 19 digits. Another value gets 400 `invalid_community_id` before the write is reserved. ListPathId: name: id in: path required: true schema: { type: string, maxLength: 2048 } description: X List ID, or the URL-encoded List link, such as x.com/i/lists/4143408. example: '4143408' BroadcastPathId: name: id in: path required: true schema: { type: string, maxLength: 2048 } description: X broadcast ID, or the URL-encoded broadcast URL, such as x.com/i/broadcasts/1nGeLMWbkpaKX. example: '1nGeLMWbkpaKX' ContributorPathAlias: name: alias in: path required: true schema: { type: string, maxLength: 2048 } description: Community Notes contributor alias, or the URL-encoded contributor URL, such as x.com/i/communitynotes/u/ardent-beach-friarbird. Any letter case works. example: ardent-beach-friarbird NotesPageSize: name: pageSize in: query description: > Notes per page (1-10, default 10). A low credit balance can return fewer. Follow next_cursor for more pages. Also read as limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 10 default: 10 SpacePathId: name: id in: path required: true schema: { type: string, maxLength: 2048 } description: X Space ID, or the URL-encoded Space URL, such as x.com/i/spaces/1OGwblLjnQMKB. example: '1OGwblLjnQMKB' CommunitySearchId: name: communityId in: query schema: { type: string, maxLength: 19, pattern: '^[1-9][0-9]{0,18}$' } description: > Numeric ID of the Community whose posts to search. Leave it out to search posts across every Community. CommunityQuery: name: q in: query required: true schema: { type: string } description: Search query CommunityQueryType: name: queryType in: query schema: { type: string, enum: [Latest, Top], default: Latest } description: Sort order (Latest or Top) CommunityFindQuery: name: q in: query required: true schema: { type: string } description: Keyword to find communities by, such as ai. Alias query. CommunityMemberQuery: name: q in: query required: true schema: { type: string } description: Name or username to find members by, such as marckohlbrugge. A leading @ is dropped. Alias query. CommunityTopicId: name: topicId in: query schema: { type: string } description: Topic or subtopic ID from /x/communities/topics, such as 301. Wins over topic. CommunityTopicName: name: topic in: query schema: { type: string } description: Topic or subtopic name in any case, such as technology. Send this or topicId. CommunityPostOrder: name: queryType in: query schema: { type: string, enum: [Latest, Top], default: Latest } description: Latest for newest first, or Top for the posts X ranks highest. Any case works. Aliases ranking & sort, which also take Recency & Relevance. Send the same value with each cursor. CommunityCursor: name: cursor in: query schema: { type: string, maxLength: 4096 } description: Pagination cursor for community search. Also read as next_cursor, next_token, pagination_token or continuation_token. WriteIdempotencyKey: name: Idempotency-Key in: header required: true description: > Use 1 unique value per intended write. Reuse it only for an identical retry. A matching retry returns the first answer again, with `idempotent: true` added. It keeps the first status, body & Retry-After. It sends nothing to X & charges nothing. While the first request runs, a retry returns 202 & the action. Different input returns 409. Protection lasts at least 90 days. schema: type: string minLength: 1 maxLength: 255 pattern: '^[!-~]{1,255}$' IdempotencyKey: name: Idempotency-Key in: header required: false description: > Generate 1 unique value per intended request. Reuse it only to retry the same request. Exact retries return the original result & charge nothing. schema: type: string minLength: 1 maxLength: 255 pattern: '^[!-~]{1,255}$' SupportIdempotencyKey: name: Idempotency-Key in: header required: false description: > Generate 1 random value per ticket or reply. Reuse it only when retrying identical text and attachments. Never log this value. schema: type: string minLength: 8 maxLength: 128 pattern: '^[A-Za-z0-9._:-]{8,128}$' GuestIdempotencyKey: name: Idempotency-Key in: header required: true description: > Generate a cryptographically random UUID v4. Reuse it only to retry the same wallet and amount request. Initial wallet creation can recover the API key from this value, so store it as a secret and never log it. schema: type: string minLength: 36 maxLength: 36 pattern: '^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$' ResourceId: name: id in: path required: true schema: type: string maxLength: 32 description: Resource ID returned by the matching create or list endpoint. example: '42' ExtractionId: name: id in: path required: true description: Extraction ID returned by `POST /extractions` or the extraction list. Another shape gets 400 `invalid_id`. schema: type: string maxLength: 12 pattern: '^[A-Za-z0-9_-]{12}$' example: 'L3NjAbCdEfGh' ConnectionChallengeId: name: id in: path required: true description: Challenge ID returned when connecting an X account asks for an email code. Another shape gets 400 `invalid_id`. schema: type: string maxLength: 20 pattern: '^xch_[A-Za-z0-9_-]{16}$' example: 'xch_AbCdEfGhIjKlMnOp' ConnectionAttemptId: name: id in: path required: true description: Connection attempt ID returned by `POST /x/accounts`. schema: type: string maxLength: 37 pattern: '^xatt_[0-9a-f]{32}$' example: 'xatt_0123456789abcdef0123456789abcdef' DrawId: name: id in: path required: true schema: type: string maxLength: 36 example: 'f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345' description: Draw public ID returned by create and list draw responses. Limit: name: limit in: query description: > Maximum items per page, from 1 to 100. Default 50. A low credit balance can return fewer paid results. When it covers none, the answer is 402 insufficient_credits. schema: type: integer minimum: 1 maximum: 100 default: 50 ListLimit: name: limit in: query description: > Maximum items per page, from 1 to 200. Default 200. Pass nextCursor as cursor for the next page. schema: type: integer minimum: 1 maximum: 200 default: 200 DeliveryLimit: name: limit in: query description: > Maximum deliveries per page, from 1 to 100. Default 100. Pass nextCursor as cursor for the next page. schema: type: integer minimum: 1 maximum: 100 default: 100 ResultPageSize: name: pageSize in: query description: > Items per page (1-100, default 20). Source, filters or credits can return fewer. Follow next_cursor for more pages. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 100 default: 20 AutomaticCoverageCursor: name: cursor in: query schema: type: string maxLength: 4096 description: > Cursor from the previous response. Existing unprefixed cursors keep legacy standard behavior. Pages can be empty before more rows. Follow next_cursor. Also read as next_cursor, next_token, pagination_token or continuation_token. AutomaticCoverageMode: name: mode in: query schema: type: string enum: [standard, coverage] description: > Omit mode for resumable maximum coverage. Standard keeps legacy pagination. Coverage returns diagnostics once and rejects cursors. AutomaticTweetPageSize: name: pageSize in: query description: > Automatic pages accept 1-300 Tweets, standard pages 1-100. Default 20. Follow next_cursor for more pages. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 300 default: 20 TweetSinceTime: name: sinceTime in: query schema: { type: string, maxLength: 64 } description: > Inclusive ISO bound for Tweet creation time, such as 2026-09-25T19:20:41Z. Unix seconds also work. A time without an offset is UTC. TweetUntilTime: name: untilTime in: query schema: { type: string, maxLength: 64 } description: > Exclusive ISO bound for Tweet creation time. Unix seconds also work. A time without an offset is UTC. LegacyCursorAlias: name: after in: query deprecated: true schema: type: string maxLength: 4096 description: Legacy cursor alias. Prefer cursor. LegacyPaginationMode: name: mode in: query schema: type: string enum: [standard] description: > Optional legacy pagination override. Search-only filters such as keywords apply only without it. TweetIncludeParentTweet: name: includeParentTweet in: query schema: { type: boolean, default: false } description: > Include each reply's parent tweet as parentTweet on the reply. A reply whose parent X does not return comes without it. Search-only filters such as keywords do not apply with it. TweetIncludeReplies: name: includeReplies in: query schema: { type: boolean, default: false } description: Include reply tweets unless replies specifies another mode. FollowerPageSize: name: pageSize in: query description: > Profiles to request from this page (1-200, default 200). Source, filters or credits can return fewer. Follow next_cursor for more pages. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 200 default: 200 UserIdPageSize: name: pageSize in: query description: > User IDs to request from this page (1-5000, default 5000). A low credit balance can return fewer. Follow next_cursor for more pages. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 5000 default: 5000 LegacyUserPageSize: name: pageSize in: query description: Maximum user profiles per page (1-200, default 20). schema: type: integer minimum: 1 maximum: 200 default: 20 LegacyFollowerLimit: name: limit in: query schema: *bounded-result-limit description: > Legacy page-size alias outside coverage mode. Coverage accepts 1-10000. Prefer pageSize. AutomaticFollowerPageSize: name: pageSize in: query description: > Up to 300 user profiles in automatic mode, 200 in standard. Sources can return fewer. Follow next_cursor for more pages. Its aliases are limit, count, max_results, maxItems, max_items & per_page. schema: type: integer minimum: 1 maximum: 300 default: 200 UserMinFollowers: name: minFollowers in: query schema: *whole-number description: Minimum follower count. Profiles the filter drops cost nothing. UserMaxFollowers: name: maxFollowers in: query schema: *whole-number description: Maximum follower count. A profile without a count passes. UserMinFollowing: name: minFollowing in: query schema: *whole-number description: Profiles must follow at least this many accounts. UserMaxFollowing: name: maxFollowing in: query schema: *whole-number description: Profiles may follow at most this many accounts. UserMinStatuses: name: minStatuses in: query schema: *whole-number description: Minimum post count. minPosts is also accepted. UserMaxStatuses: name: maxStatuses in: query schema: *whole-number description: Maximum post count. maxPosts is also accepted. UserMinAccountAgeDays: name: minAccountAgeDays in: query schema: *whole-number description: Minimum account age in whole days. UserVerifiedOnly: name: verifiedOnly in: query schema: { type: boolean } description: Only return verified profiles. UserBlueVerifiedOnly: name: blueVerifiedOnly in: query schema: { type: boolean } description: > Only return profiles X marks as blue verified. X marks many business & government accounts blue too. Use verifiedType for 1 badge type. UserVerifiedType: name: verifiedType in: query schema: { type: string, maxLength: 100 } description: Match the verification type exactly, ignoring case. EnrichProfiles: name: enrichProfiles in: query schema: { type: boolean, default: false } description: > Add each row's full profile, as GET /x/users/{id} returns it. Pages take several seconds longer. UserHasWebsite: name: hasWebsite in: query schema: { type: boolean } description: Only return profiles with a website. UserHasLocation: name: hasLocation in: query schema: { type: boolean } description: Only return profiles with a location. UserListMaxScan: name: maxScan in: query schema: { type: integer, minimum: 1 } description: > Most profiles 1 request reads, kept or dropped by the filters. The request then answers the profiles it kept, the count it dropped & the cursor to read on. Each request of a cursor may send its own value. Without it, a filtered read scans at most 100,000 profiles of the list across all its pages, & the page that reaches them ends the list with `scanLimit`. An unfiltered read has no scan limit. Automatic mode only. example: 10000 UserHasEmail: name: hasEmail in: query schema: { type: boolean } description: Only return profiles that publish an email. UserBusinessEmailOnly: name: businessEmailOnly in: query schema: { type: boolean } description: > Only return profiles that publish an email outside free webmail, such as Gmail. UserEmailDomains: name: emailDomains in: query schema: { type: string, maxLength: 4096 } description: > Only return profiles with an email at one of these domains. Separate domains with commas. Subdomains match. example: acme.com,stanford.edu UserBioContains: name: bioContains in: query schema: { type: string, maxLength: 4096 } description: > Match any comma-separated or line-separated bio term, ignoring case. UserLocationContains: name: locationContains in: query schema: { type: string, maxLength: 100 } description: Match a location substring, ignoring case. UserUsernameContains: name: usernameContains in: query schema: { type: string, maxLength: 100 } description: Match a username substring, ignoring case. After: name: cursor in: query schema: type: string maxLength: 128 description: > Previous nextCursor. The after alias also works. Offset pagination is not supported. StyleId: name: id in: path required: true schema: type: string maxLength: 64 description: Style profile ID or X username. Case and a leading @ are ignored. example: 'nasa' FromUser: name: fromUser in: query schema: type: string maxLength: 19 description: Filter by author username. ToUser: name: toUser in: query schema: type: string maxLength: 19 description: Filter replies sent to a username. Mentioning: name: mentioning in: query schema: type: string maxLength: 19 description: Filter tweets mentioning a username. Language: name: language in: query schema: type: string maxLength: 35 description: Filter by language. Its alias is `lang`. SinceDate: name: sinceDate in: query schema: type: string format: date maxLength: 64 description: Start date in YYYY-MM-DD format, as a UTC day. UntilDate: name: untilDate in: query schema: type: string format: date maxLength: 64 description: End date in YYYY-MM-DD format, as a UTC day, inclusive, so its own posts count. MediaType: name: mediaType in: query schema: type: string enum: [images, videos, gifs, media, links, none] description: 'Filter media. Its aliases are has_video & has_media.' MinLikes: name: minLikes in: query schema: &nonnegative-integer $ref: '#/components/schemas/WholeNumber' description: 'Minimum likes. Its aliases are minFaves, min_likes & min_faves.' MinRetweets: name: minRetweets in: query schema: *nonnegative-integer description: Minimum retweets threshold. MinReplies: name: minReplies in: query schema: *nonnegative-integer description: Minimum replies threshold. MinQuotes: name: minQuotes in: query schema: *nonnegative-integer description: Minimum quote count threshold. MinViews: name: minViews in: query schema: *nonnegative-integer description: Minimum view count threshold. MinBookmarks: name: minBookmarks in: query schema: *nonnegative-integer description: Minimum bookmark count threshold. MaxFaves: name: maxFaves in: query schema: *nonnegative-integer description: Maximum likes threshold. maxLikes & max_likes also work. MaxRetweets: name: maxRetweets in: query schema: *nonnegative-integer description: Maximum retweets threshold. MaxReplies: name: maxReplies in: query schema: *nonnegative-integer description: Maximum replies threshold. MaxQuotes: name: maxQuotes in: query schema: *nonnegative-integer description: Maximum quotes threshold. BlueVerifiedOnly: name: blueVerifiedOnly in: query schema: type: boolean description: Only return tweets from Blue-verified authors. CardName: name: cardName in: query schema: { type: string, maxLength: 512 } description: > Keep only Tweets with this card type, such as poll2choice_text_only. Tweet search checks each Tweet's card. Source: name: source in: query schema: { type: string, maxLength: 512 } description: > X search no longer supports source. A Tweet search with it answers 424 & charges nothing. ExcludeSource: name: excludeSource in: query schema: { type: string, maxLength: 512 } description: > X search no longer supports excludeSource. A Tweet search with it answers 424 & charges nothing. Geocode: name: geocode in: query schema: { type: string, maxLength: 512 } description: > X search no longer supports geocode. A Tweet search with it answers 424 & charges nothing. SinceId: name: sinceId in: query schema: { type: string, maxLength: 19 } description: Return Tweets whose IDs exceed this ID. MaxId: name: maxId in: query schema: { type: string, maxLength: 19 } description: Return Tweets at or below this ID. Near: name: near in: query schema: { type: string, maxLength: 512 } description: > A place name. A country, such as United States, works like placeCountry & keeps Tweets tagged there. A city keeps Tweets about it. Within: name: within in: query schema: { type: string, maxLength: 512 } description: > X search no longer supports within. A Tweet search with it answers 424 & charges nothing. Use near alone. WithinTime: name: withinTime in: query schema: type: string maxLength: 64 example: '7d' description: > Keeps Tweets from a recent window, such as 90m or 7d. Use a whole number & s, m, h or d. NativeRetweets: name: nativeRetweets in: query schema: { type: boolean } description: Only return native reposts. Safe: name: safe in: query schema: { type: boolean } description: Enable the safe-search filter. News: name: news in: query schema: { type: boolean } description: X no longer searches filter:news. VerifiedOnly: name: verifiedOnly in: query schema: type: boolean description: Only return tweets from verified authors. Replies: name: replies in: query schema: type: string enum: [include, exclude, only] description: Reply mode. Exclude keeps own-thread replies. SearchReplies: name: replies in: query schema: type: string enum: [include, exclude, only] description: Reply mode. Exclude drops every reply, own-thread replies too. Retweets: name: retweets in: query schema: type: string enum: [include, exclude, only] description: Only when the caller requests a repost mode. Quotes: name: quotes in: query schema: type: string enum: [include, exclude, only] description: Only when the caller requests a quote mode. ExactPhrase: name: exactPhrase in: query schema: type: string maxLength: 4096 description: Match this literal phrase, including any hyphens. ExcludeWords: name: excludeWords in: query schema: type: string maxLength: 4096 description: Words or quoted phrases to exclude. Separate with spaces, commas, or lines. AnyWords: name: anyWords in: query schema: type: string maxLength: 4096 description: Words or quoted phrases where any one can match. Separate with spaces, commas, or lines. Hashtags: name: hashtags in: query schema: type: string maxLength: 4096 description: Hashtags separated by spaces, commas, or lines. Cashtags: name: cashtags in: query schema: type: string maxLength: 4096 description: Cashtags separated by spaces, commas, or lines. Url: name: url in: query schema: type: string maxLength: 2048 description: URL substring or domain filter. ConversationId: name: conversationId in: query schema: type: string maxLength: 19 description: Conversation ID filter. InReplyToTweetId: name: inReplyToTweetId in: query schema: type: string maxLength: 19 description: Only replies to this tweet ID. QuotesOfTweetId: name: quotesOfTweetId in: query schema: type: string maxLength: 19 description: Only quotes of this tweet ID. RetweetsOfTweetId: name: retweetsOfTweetId in: query schema: type: string maxLength: 19 description: Only retweets of this tweet ID. Keywords: name: keywords in: query schema: type: string maxLength: 4096 description: Words the Tweets must match, in X search syntax. ListId: name: listId in: query schema: type: string maxLength: 19 description: Search within a list ID. Place: name: place in: query schema: type: string maxLength: 512 description: Search within a place ID. PlaceCountry: name: placeCountry in: query schema: type: string maxLength: 512 description: Search within a country code. PointRadius: name: pointRadius in: query schema: type: string maxLength: 512 description: Geo point radius, such as -73.99 40.73 25mi. BoundingBox: name: boundingBox in: query schema: type: string maxLength: 512 description: Geo bounding box, such as -74.1 40.6 -73.9 40.8. AdvancedQuery: name: advancedQuery in: query schema: type: string maxLength: 4096 description: Raw advanced search query appended as-is. Fields: name: fields in: query schema: type: string maxLength: 13085 example: id,text,author.username description: > Fields to keep in each row, comma-separated. Use dots for nested fields, such as author.username. A list keeps the field in each item. Case & underscores do not matter. A row that lacks a field leaves it out. Cursors, counts & diagnostics always stay. An unknown name answers 400 unknown_field with the valid names, before any read. The price stays the same. SDK row types then hold only the named fields. A longer URL fails at the edge before Xquik reads it. Omit: name: omit in: query schema: type: string maxLength: 13087 example: entities,media description: > Fields to drop from each row, comma-separated. It takes the same names as fields. With fields, it drops from the kept fields. A longer URL fails at the edge before Xquik reads it. headers: RateLimit: description: > Your requests left in this window & seconds until it resets, for the limit this request counts against. schema: type: string pattern: '^"[a-z-]+";r=\d+;t=\d+$' example: '"read";r=499;t=1' CreditsCharged: description: > Credits this request charged. 0 when it charged none, as for a page a filter empties or a page sent again. schema: type: string pattern: '^\d+$' example: '3' RateLimitPolicy: description: > Your limit for this kind of request, as q requests per w seconds. schema: type: string pattern: '^"[a-z-]+";q=\d+;w=\d+$' example: '"read";q=500;w=1' BusyRetryAfter: description: Seconds before a retry. schema: *positive-integer XquikBusy: description: Xquik bills nothing. Retry after Retry-After until your deadline. schema: type: string enum: ['true'] XquikBusyReason: description: 'The busy part of Xquik, admission or reads.' schema: type: string enum: ['admission', 'reads'] XquikCause: description: > Sent when X's servers failed the request. The value x names X as the cause. Xquik's own failures & other answers omit this header. schema: type: string enum: ['x'] ProfileEnrichment: description: > Sent with enrichProfiles=true. How many returned rows carry the full profile. Rows without it keep their list fields. schema: type: string pattern: '^enriched=\d+; requested=\d+$' example: 'enriched=180; requested=200' Deprecation: description: > Sent when this request uses a deprecated part of this operation, such as a parameter, a search filter or a response field. It holds the Unix time of the deprecation, as RFC 9745 defines. schema: type: string pattern: '^@\d+$' example: '@1777420800' DeprecationLink: description: > Sent with Deprecation. Its rel="deprecation" link points to the deprecation policy. schema: type: string example: '; rel="deprecation"; type="text/markdown"' Sunset: description: > Sent once a removal date is set. The deprecated part stops working on this HTTP date, as RFC 8594 defines. schema: type: string example: 'Fri, 15 Jan 2027 00:00:00 GMT' responses: SessionRequired: description: > An API key or OAuth token called a route that needs a dashboard session. Sign in at dashboard.xquik.com/account instead. content: application/json: schema: *error-schema example: *session-required-example IdempotencyConflict: description: Idempotency-Key was reused with another request. content: application/json: schema: { $ref: '#/components/schemas/Error' } example: error: idempotency_conflict message: Idempotency-Key belongs to another request. Use a new key. CommunityTweetSearchResults: description: Tweet search results from the selected X Community content: *paginated-tweets-content WriteActionCompleted: description: Write reached a terminal state. headers: X-Request-Id: required: true description: Correlation ID for support and observability. schema: type: string Location: description: Relative URL for the durable action record. schema: type: string content: application/json: schema: $ref: '#/components/schemas/XWriteAction' example: object: x_write_action id: '12345' writeActionId: '12345' action: like status: success terminal: true retryable: false safeToRetry: false statusUrl: /api/v1/x/write-actions/12345 pollAfterMs: null charged: true chargedCredits: '10' billing: status: charged charged: true plannedCredits: '10' chargedCredits: '10' request: hash: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef payload: tweet_id: '9876543210' account: id: '42' username: example target: type: tweet id: '9876543210' targetId: '9876543210' result: type: state_change id: '9876543210' state: liked nextAction: null sendDispatched: true success: true WriteActionAccepted: description: > Write accepted or dispatched. Poll Location after Retry-After. Send no other write until it ends. X's 408, 500, 502, 503 or 504 after the send gives x_write_ambiguous. headers: X-Request-Id: required: true description: Correlation ID of the accepted write. schema: type: string Location: required: true description: Relative URL for polling the durable action record. schema: type: string Retry-After: required: true description: Recommended polling delay in seconds. schema: *positive-integer content: application/json: schema: $ref: '#/components/schemas/XWriteAction' example: object: x_write_action id: '12346' writeActionId: '12346' action: create_tweet status: dispatching terminal: false retryable: false safeToRetry: false statusUrl: /api/v1/x/write-actions/12346 pollAfterMs: 2000 charged: false chargedCredits: '0' billing: status: pending charged: false plannedCredits: '30' chargedCredits: '0' request: hash: abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789 payload: text: 'Hello from Xquik' account: id: '42' username: example target: null targetId: null result: null nextAction: type: poll url: /api/v1/x/write-actions/12346 afterMs: 2000 sendDispatched: true success: false WriteIdempotencyConflict: description: The idempotency key belongs to a different write request. headers: X-Request-Id: required: true description: Correlation ID of the conflict. schema: type: string content: application/json: schema: $ref: '#/components/schemas/XWriteActionError' example: charged: false chargedCredits: '0' error: idempotency_conflict message: Idempotency-Key was already used with a different request. safeToRetry: true retryable: false success: false nextAction: type: retry requiresNewIdempotencyKey: true WriteInvalidInput: description: The write request is invalid. Xquik dispatched no action. headers: X-Request-Id: required: true description: Correlation ID of the invalid write. schema: type: string content: application/json: schema: $ref: '#/components/schemas/XWriteActionError' examples: missingIdempotencyKey: summary: Missing Idempotency-Key header value: error: missing_idempotency_key message: Idempotency-Key is required. Generate one unique key for this write. charged: false chargedCredits: '0' retryable: false safeToRetry: true success: false nextAction: type: fix_request fieldErrors: - code: required message: Idempotency-Key is required. Generate one unique key for this write. path: headers.Idempotency-Key invalidIdempotencyKey: summary: Invalid Idempotency-Key header value: error: invalid_idempotency_key message: Idempotency-Key must contain 1-255 visible ASCII characters. charged: false chargedCredits: '0' retryable: false safeToRetry: true success: false nextAction: type: fix_request fieldErrors: - code: invalid message: Idempotency-Key must contain 1-255 visible ASCII characters. path: headers.Idempotency-Key invalidInput: summary: Invalid request fields value: error: invalid_input message: Invalid input. Check request fields. charged: false chargedCredits: '0' retryable: false safeToRetry: true success: false nextAction: type: fix_request WriteTrackingUnavailable: description: > Tracking or the write service is down. X's 408, 500, 502, 503 or 504 before the send gives x_transient_error. Check safeToRetry. headers: X-Request-Id: required: true description: Correlation ID for this tracking failure. schema: type: string Retry-After: description: Recommended retry delay in seconds. schema: *positive-integer content: application/json: schema: oneOf: - $ref: '#/components/schemas/XWriteActionError' - $ref: '#/components/schemas/XWriteAction' example: error: write_tracking_unavailable message: Write tracking unavailable. Try again. charged: false chargedCredits: '0' retryable: true safeToRetry: true success: false nextAction: type: retry Success: description: Success content: application/json: schema: type: object required: [success] properties: success: type: boolean const: true example: true example: success: true MonitorDeletionAccepted: description: Monitor deletion started headers: Location: description: Monitor URL that reports deletion progress. schema: type: string Retry-After: description: Wait this many seconds before polling again. schema: *positive-integer content: application/json: schema: type: object additionalProperties: false required: [deletionStatus, statusUrl, success] properties: deletionStatus: type: string const: deleting statusUrl: type: string description: Poll this monitor URL until it returns 404. example: /api/v1/monitors/42 success: *boolean-true example: deletionStatus: deleting statusUrl: /api/v1/monitors/42 success: true NoContent: description: Deleted Unauthenticated: description: Unauthenticated headers: Cache-Control: description: Prevents storage of authentication responses. schema: *no-store-header WWW-Authenticate: description: Bearer authentication challenge. schema: type: string const: 'Bearer realm="xquik"' content: application/json: schema: *error-schema example: error: 'unauthenticated' message: 'Authentication required. Provide a valid API key or bearer token.' AnonymousGuestAuthenticationRequired: description: > Non-MPP paid reads require Bearer authentication. Without credentials, the answer offers a guest checkout but does not create it. Invalid credentials return a plain error. Confirm before using any offered action. headers: Cache-Control: description: Prevents storage of the guest checkout action. schema: *no-store-header WWW-Authenticate: description: Bearer authentication challenge, not a Payment challenge. schema: type: string const: 'Bearer realm="xquik"' content: application/json: schema: oneOf: - $ref: '#/components/schemas/AnonymousGuestAuthenticationRequired' - allOf: - $ref: '#/components/schemas/Error' - type: object propertyNames: not: { const: payment_options, type: string } type: string example: account_required: false error: unauthenticated message: Authentication required. next_step: Ask the user to confirm a USD amount before creating checkout. payment_options: &guest-checkout-payment-options guest_wallet: create_checkout: account_required: false amount_bounds: currency: usd maximum_minor: 25000 minimum_minor: 1000 body: { amount_minor: 1000, currency: usd } creates: checkout_url method: POST path: /api/v1/guest-wallets provider: stripe required_headers: Idempotency-Key: requires_authentication: false requires_user_confirmation: true requires_user_interaction: true response_fields: [checkout_url, api_key, status_url] response_url_field: checkout_url InvalidInput: description: > Invalid input. A value past its maxLength gets this answer, & the message names the field & its limit. content: application/json: schema: *error-schema example: error: 'invalid_input' message: 'Invalid input. Check the request body.' UnknownField: description: > A name in fields or omit names no field of the answer. Xquik reads & charges nothing. content: application/json: schema: *error-schema example: error: 'unknown_field' message: 'Unknown field asetUrl. Did you mean assetUrl?' fieldErrors: - code: 'unknown_field' field: 'asetUrl' message: 'Unknown field asetUrl. Did you mean assetUrl?' path: 'query.fields' suggestion: 'assetUrl' allowedFields: - 'hashtag' - 'assetUrl' - 'startsAt' - 'endsAt' - 'isHashfettiEnabled' - 'animations' NotFound: description: Not found content: application/json: schema: *error-schema example: error: 'not_found' message: 'Resource not found.' TweetNotFound: description: > X shows no post with this ID. `reason` says why when X's answer named it. It is `deleted` with the message "The author deleted this post.", `author_suspended` with "X suspended this post's author.", or `protected` with "This post's author limits who can see it." Without `reason`, X named no cause, and the message is "Tweet not found. Check the tweet ID." content: application/json: schema: *error-schema example: error: 'tweet_not_found' message: 'Tweet not found. Check the tweet ID.' UserNotFound: description: > X shows no profile for the account. `reason` says why. It is `not_found` for a handle or ID no account holds, which X answers for a deactivated account too, or `suspended` with the message "X suspended this account. Choose another account." when X suspended it. content: application/json: schema: *error-schema example: error: 'user_not_found' message: 'X user not found. Check the username.' reason: 'not_found' ContributorNotFound: description: No contributor holds the alias. Free. content: application/json: schema: *error-schema example: error: 'contributor_not_found' message: 'Contributor not found. Check the alias on its x.com/i/communitynotes/u page.' ContributorNotesInvalidInput: description: > Text that is no alias returns invalid_contributor_alias. A cursor X never issued returns invalid_cursor. Start again without it. Both are free. content: application/json: schema: *error-schema examples: invalid_contributor_alias: value: error: 'invalid_contributor_alias' message: 'Send a Community Notes alias or its x.com/i/communitynotes/u URL.' invalid_cursor: value: error: 'invalid_cursor' message: 'Cursor invalid or expired. Start again without cursor, then use next_cursor.' PaymentRequired: description: > Payment required. MPP reads include `WWW-Authenticate`. Authenticated reads include balances and checkout. A failed request never creates checkout. A caller on a plan gets top-up only, plus `credits_renew_at` when the plan renews. Guest keys offer top-up. headers: WWW-Authenticate: description: MPP payment challenge for eligible anonymous pay-per-use requests. Authenticated credit or subscription errors omit this header. schema: type: string content: application/json: schema: oneOf: - $ref: '#/components/schemas/XWritePaymentRequired' - $ref: '#/components/schemas/AuthenticatedPaymentRequired' - $ref: '#/components/schemas/GuestPaymentRequired' - allOf: - $ref: '#/components/schemas/Error' - type: object propertyNames: not: { const: payment_options, type: string } type: string example: balance: '0' dashboard: '/dashboard/account' error: insufficient_credits message: Insufficient credits. Top up or subscribe to continue. next_step: Ask the user to confirm a payment option before creating checkout. payment_options: credits: create_checkout: body: dollars: 10 locale: en creates: checkout_url method: POST path: /api/v1/credits/topup provider: stripe requires_authentication: true requires_user_confirmation: true response_url_field: url subscription: create_checkout: body: tier: starter creates: checkout_url method: POST path: /api/v1/subscribe provider: stripe requires_authentication: true requires_user_confirmation: true response_url_field: url required: '1' top_up_endpoint: /api/v1/credits/topup top_up_url: POST /api/v1/credits/topup application/problem+json: schema: $ref: '#/components/schemas/MppPaymentRequired' example: account_required: false challengeId: Opaque MPP challenge identifier detail: Payment is required. hint: Use a supported wallet with an offer from the WWW-Authenticate header. status: 402 title: Payment Required type: https://paymentauth.org/problems/payment-required next_step: Ask the user to confirm a USD amount before creating checkout. payment_options: *guest-checkout-payment-options GuestForbidden: description: Not open to guest keys. content: application/json: schema: *error-schema example: error: forbidden message: This API key can access paid read endpoints only. ProtectedTimeline: description: >- The account is protected. Choose a public one. This applies to every timeline page & mode. Xquik charges nothing. Profile lookup still works. content: application/json: schema: *error-schema example: error: x_account_protected message: Account is protected. Choose a public account. ProtectedTarget: description: The target account is protected. Choose a public one. Xquik creates no job & charges nothing. Follower tools name the private list. content: application/json: schema: *error-schema example: error: x_account_protected message: Account is protected. Choose a public account. ProtectedFollowerList: description: X keeps a protected account's follower list private. Xquik charges nothing. content: application/json: schema: *error-schema example: error: x_account_protected message: This account's follower list is private. Try a public account. ProtectedFollowingList: description: X keeps a protected account's following list private. Xquik charges nothing. content: application/json: schema: *error-schema example: error: x_account_protected message: This account's following list is private. Try a public account. ProtectedVerifiedFollowerList: description: X keeps a protected account's verified follower list private. Xquik charges nothing. content: application/json: schema: *error-schema example: error: x_account_protected message: This account's verified follower list is private. Try a public account. AccountAuthError: description: > The connected X account needs reauthentication or is restricted (locked, suspended, or recovering). The error code is `account_needs_reauth` or `account_restricted`. content: application/json: schema: *error-schema example: error: 'account_needs_reauth' message: 'X account needs re-authentication. Re-add the account.' MediaTooLarge: description: The media is over Xquik's or X's size limit. content: application/json: schema: *error-schema example: error: 'media_too_large' message: "This image stays over X's size limit after shrinking. Send a smaller one." UnsupportedMedia: description: The file isn't a supported, readable image or video. content: application/json: schema: *error-schema example: error: 'unsupported_media_type' message: "Xquik couldn't read this image. Send a valid image file." XAccountNotFound: description: Connected X account not found content: application/json: schema: *error-schema example: error: 'account_not_found' message: 'X account not found. Connect it first at /dashboard/account?tab=x-accounts.' WriteError: description: > Write failed. Check error, safeToRetry & nextAction. x_write_failed means Xquik can't explain it. content: application/json: schema: *error-schema example: error: 'x_write_failed' message: 'Write action failed unexpectedly. Contact support if this persists.' WriteRejected: description: > X rejected the write or download. Error.code says why. `x_automation_refused` needs no wait. `x_reply_not_allowed` repeats X's refusal of a reply for 1 hour, 4 hours after X refuses it again & 24 hours after each later refusal, with `Retry-After`. Media can fail on its URL, size, origin or timeout. A post into a Community gets `x_community_not_joined` when the account isn't a member, `x_community_not_selectable` when X's composer can't pick it, & `x_community_post_removed` or `x_community_post_public` when X put it outside the Community. Xquik charges nothing for any of them. headers: Retry-After: description: Seconds until X may take the reply again, when known. schema: *positive-integer content: application/json: schema: *error-schema example: error: 'x_rejected' message: 'X rejected this request. Check what you sent & the account on x.com before you try again.' RateLimitedByX: description: > X throttled the write, with `x_rate_limited` (short-term) or `x_daily_limit` (daily cap). Retry later. This differs from Xquik's tier-based 429. content: application/json: schema: *error-schema example: error: 'x_rate_limited' message: 'X rate limited this account. Try again in about 15 minutes. Send fewer requests from this account.' WriteRateLimited: description: > The write hit an Xquik limit or X's `x_rate_limited`. Follow `Retry-After` when present. Otherwise back off before retrying. The follow limit's `Retry-After` is the wait until it frees, up to 24 hours. headers: Retry-After: description: Seconds to wait before retrying, when known. schema: *positive-integer content: application/json: schema: &retry-after-error-schema allOf: - $ref: '#/components/schemas/Error' - type: object properties: retryAfter: type: integer minimum: 0 example: 60 examples: xquikLimit: summary: Xquik tier limit value: error: 'rate_limit_exceeded' message: 'Too many requests. Try again later.' retryAfter: 60 followLimit: summary: Follow limit value: error: 'rate_limit_exceeded' message: 'Too many follow actions. Try again in 23 hours.' retryAfter: 82800 XApiError: description: > Dependency unavailable, unauthorized, or limited. Default v1 uses 502. Best-practice responses use 424 for transparent dependency failures. Search answers 424 `search_unavailable` when X fails the query itself, or when its filters matched none of the last 3,000 posts read. The message says how far back the search read. headers: X-Xquik-Cause: $ref: '#/components/headers/XquikCause' content: application/json: schema: *error-schema example: error: 'x_api_unavailable' message: 'X data source temporarily unavailable. Try again later.' FavoritersUnavailable: description: > X reports likes for the post and withholds the users, because X shows likers only to the post author. Returns error code `favoriters_unavailable`. content: application/json: schema: *error-schema example: error: 'favoriters_unavailable' message: 'Users who liked this post are unavailable. X shows likers only to the post author. Use retweeters or replies instead.' CoverageCursorUnavailable: description: Xquik is still reading the cursor's page. Your key or session repeating the same request waits for that page instead. Wait `Retry-After` seconds, then send the same cursor again. headers: Retry-After: required: true schema: *positive-integer description: Seconds to wait. content: application/json: schema: *error-schema example: error: 'coverage_cursor_unavailable' message: 'Cursor busy. Retry after the indicated delay.' CursorGone: description: Restart without the `coverage_cursor_gone` cursor. A cursor sent again within 10 minutes of its page returns the same page at no charge, so only an older, expired or replaced cursor answers 410. content: application/json: schema: *error-schema example: error: 'coverage_cursor_gone' message: 'Cursor finished, expired, or superseded. Restart pagination without cursor.' MaximumCoverageBusy: description: Retry x_api_unavailable after Retry-After. Retry pagination_stalled once after 30 s. headers: &busy-headers X-Xquik-Cause: $ref: '#/components/headers/XquikCause' Retry-After: $ref: '#/components/headers/BusyRetryAfter' X-Xquik-Busy: $ref: '#/components/headers/XquikBusy' X-Xquik-Busy-Reason: $ref: '#/components/headers/XquikBusyReason' content: application/json: schema: *error-schema example: error: 'x_api_unavailable' message: 'Maximum coverage is busy. Retry shortly.' ReadBusy: description: Retry x_api_unavailable after Retry-After. With X-Xquik-Busy, retry until your deadline. headers: *busy-headers content: application/json: schema: *error-schema example: error: 'x_api_unavailable' message: 'Xquik is busy right now. Retry shortly.' TweetAnalysisPage: description: Analyzed posts, posts without an analysis & their totals content: application/json: schema: $ref: '#/components/schemas/TweetAnalysisPage' example: results: - tweet: id: '1893456789012345678' text: 'The new headphones sound great. The app keeps crashing.' retweetCount: 4 replyCount: 2 likeCount: 31 quoteCount: 0 viewCount: 2140 bookmarkCount: 1 analysis: status: 'succeeded' answers: - questionId: 'sentiment' questionVersion: 'sentiment:2' type: 'choice' value: 'mixed' confidence: 0.88 probabilities: positive: 0.06 negative: 0.04 mixed: 0.88 neutral: 0.01 unclear: 0.01 - questionId: 'intensity' questionVersion: 'sentiment:2' type: 'score' value: 1 confidence: 0.81 probabilities: { '0': 0.05, '1': 0.81, '2': 0.14 } levels: - 'No attitude or a passing mention.' - 'A clear but measured attitude.' - 'An emphatic or emotional attitude with strong wording.' - questionId: 'sarcasm' questionVersion: 'sentiment:2' type: 'probability' probability: 0.03 questions: - { id: 'sentiment', version: 'sentiment:2' } - { id: 'intensity', version: 'sentiment:2' } - { id: 'sarcasm', version: 'sentiment:2' } contextBytes: 612 contextAvailability: quote: 'not_applicable' reply: 'not_applicable' author: 'available' media: 'not_supplied' article: 'not_supplied' postText: 'full' answers: { sentiment: 'mixed', intensity: 1, sarcasm: 0.03 } sourceDomains: [] cashtags: [] monitor: configurationFingerprint: '9f2c4e1b7a5d3c8e6f0a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f6a' baselineDatasetId: null status: 'changed' changedQuestionIds: ['sentiment'] changes: - questionId: 'sentiment' previous: 'positive' current: 'mixed' unanalyzed: - id: '1893456789012345679' status: 'skipped' reason: 'post_unavailable' analysisSummary: schemaVersion: 1 rows: { analyzed: 1, failed: 0, skipped: 0 } engagement: 37 questions: sentiment: type: 'choice' counts: { positive: 0, negative: 0, mixed: 1, neutral: 0, unclear: 0, } shares: { positive: 0, negative: 0, mixed: 1, neutral: 0, unclear: 0, } targets: [] cashtags: [] sourceDomains: [] monitor: statuses: { changed: 1 } changedRows: - tweetId: '1893456789012345678' changes: - questionId: 'sentiment' previous: 'positive' current: 'mixed' has_next_page: false next_cursor: '' RepliesIncomplete: description: X did not expose every reply. Xquik bills returned rows as usual. An answer cut by your own limit returns 200 with limit_reached. A post that shows none of the replies it counts returns 200 with hiddenReplies. content: application/json: schema: anyOf: - $ref: '#/components/schemas/Error' - $ref: '#/components/schemas/IncompleteTweetReplies' example: error: 'replies_incomplete' message: 'Replies are incomplete. Retry complete mode later.' tweets: [] has_next_page: false next_cursor: '' nested_replies: [] diagnostic: complete: false reportedReplyCount: 100 targetDirectReplies: 80 uniqueDirectReplies: 42 coveragePercentage: 42 nestedReplyCount: 5 pagesAttempted: 12 strategiesAttempted: [] duplicateCount: 3 cursorFailures: 0 repeatedCursorCount: 0 emptyFalseProgressPages: 1 malformedCount: 0 unrelatedCount: 2 missingResponseModulesOrFields: [] recommendedFallback: 'Retry complete mode later. X did not expose enough direct replies.' richness: totalReplies: 42 text: 42 author: 40 createdAt: 42 language: 38 url: 42 entities: 20 media: 5 article: 0 card: 2 communityNote: 0 quotedOrRepostedTweet: 1 engagementCounts: 42 responseTruncated: false sourcesEnded: false ConnectAlreadyConnected: description: > This X account is already connected to this Xquik account. The error code is `account_already_connected`. content: application/json: schema: *error-schema example: error: 'account_already_connected' message: 'This X account is already connected.' ConnectLoginFailed: description: > Login requires new credentials, account verification, or a wait. Cooldowns include `retryAfterMs` and `Retry-After`. Codes are `login_failed` or `passkey_required`. `reason` is `account_not_found` (unknown username), `repeated_login_error`, or `login_unconfirmed` (X showed no known page after the password). Retrying a `login_unconfirmed` login before `Retry-After` can make X lock the account. headers: Retry-After: description: Cooldown duration in seconds, when retrying must wait. schema: *positive-integer content: application/json: schema: *error-schema example: error: 'login_failed' message: 'Login failed. Check credentials and try again.' retryAfterMs: 300000 ConnectLoginCooldown: description: > A prior login attempt triggered a cooldown. The response has `reason`, `retryAfterMs` & a `Retry-After` header in seconds. The error code is `login_cooldown`. headers: Retry-After: description: Cooldown duration in seconds. required: true schema: *positive-integer content: application/json: schema: *error-schema example: error: 'login_cooldown' message: 'Login is temporarily paused' reason: 'temporary_issue' retryAfterMs: 60000 ConnectRateLimitExceeded: description: > Too many requests. `rate_limit_exceeded` includes `retryAfter` and `Retry-After`. `login_cooldown` also includes `reason` and `retryAfterMs`. headers: Retry-After: description: Required wait in seconds. required: true schema: *positive-integer content: application/json: schema: *error-schema example: error: 'rate_limit_exceeded' message: 'Too many requests. Retry later.' RateLimitExceeded: description: > Too many requests right now. Each user gets 500 reads a second. Each minute allows 120 writes & 60 deletes. `x_api_rate_limited` means X limits this read for now. Neither answer costs anything. Wait for the seconds in `Retry-After`, then retry. headers: RateLimit: { $ref: '#/components/headers/RateLimit' } RateLimit-Policy: { $ref: '#/components/headers/RateLimitPolicy' } Retry-After: description: Seconds to wait before a retry. schema: *positive-integer content: application/json: schema: *retry-after-error-schema examples: xquikLimit: summary: Xquik limit value: error: 'rate_limit_exceeded' message: 'Too many requests. Try again later.' retryAfter: 60 xReadLimit: summary: X read limit value: error: 'x_api_rate_limited' message: "Your X account hit X's read limit. Try again in 10 minutes." retryAfter: 600 GuestWalletRateLimited: description: Guest wallet request limit exceeded. headers: Retry-After: description: Seconds before the next guest wallet request. required: true schema: *positive-integer content: application/json: schema: *error-schema example: error: 'rate_limited' message: 'Try again later.' ConnectUserLookupFailed: description: > X couldn't resolve this username. Check the handle & that the account exists. Default v1 returns 502. The best-practice contract returns 424. The error code is `x_user_lookup_failed`. content: application/json: schema: *error-schema example: error: 'x_user_lookup_failed' message: 'X username lookup failed. Try again later.' ConnectServiceUnavailable: description: > The X connection service is temporarily unavailable. Retry shortly. The error code is `service_unavailable`. content: application/json: schema: *error-schema example: error: 'service_unavailable' message: 'Service temporarily unavailable. Try again later.' ReauthAccountNotFound: description: > No X account with this ID belongs to the authenticated user. Returns error code `account_not_found`. content: application/json: schema: *error-schema example: error: 'account_not_found' message: 'X account not found.' schemas: NextCursor: description: Cursor for the next page. Send it unchanged. type: string example: 'DAACCgACGRElMJcAAA' WholeNumber: description: Whole number from 0. type: integer minimum: 0 SupportReceipt: description: Support submission receipt. type: object required: [publicId, attachments] properties: publicId: *ticket-id-example-schema attachments: type: array example: [] items: $ref: '#/components/schemas/SupportAttachmentReceipt' GuestPaymentOptions: description: Accountless checkout options. type: object additionalProperties: false required: [guest_wallet] properties: guest_wallet: type: object additionalProperties: false required: [create_checkout] properties: create_checkout: $ref: '#/components/schemas/GuestWalletCreateCheckoutAction' NlwebAskRequest: description: Public NLWeb documentation search request. type: object example: { query: 'How does MCP OAuth work?' } required: [query] additionalProperties: true properties: query: example: How does MCP OAuth work? oneOf: - type: string minLength: 1 maxLength: 500 description: Natural-language documentation query. - type: object required: [text] additionalProperties: true properties: text: { type: string, minLength: 1, maxLength: 500 } site: type: string enum: [docs.xquik.com, xquik.com] site: example: docs.xquik.com type: string enum: [docs.xquik.com, xquik.com] streaming: { type: boolean, default: false, example: false } response_format: example: conversational_search type: string default: conversational_search enum: [chatgpt_app, conversational_search] mode: { type: string, const: list, example: list } context: type: object example: { previous_query: 'How does OAuth work?' } additionalProperties: true description: Optional NLWeb conversational context. prefer: type: object example: { mode: list, response_format: chatgpt_app, streaming: false } additionalProperties: true properties: streaming: type: boolean response_format: type: string enum: [chatgpt_app, conversational_search] mode: type: string enum: [list] meta: example: { api_version: '0.55' } type: object additionalProperties: true properties: api_version: type: string enum: ['0.54', '0.55'] version: type: string enum: ['0.54', '0.55'] NlwebMeta: description: NLWeb response metadata. type: object required: [response_type, version] properties: response_type: type: string enum: [answer, failure] response_format: type: string enum: [chatgpt_app, conversational_search] version: type: string const: '0.55' NlwebDocumentationResult: description: Public Xquik documentation result using schema.org. type: object required: ['@context', '@id', '@type', description, name, url] properties: '@context': type: string const: https://schema.org '@id': type: string format: uri '@type': type: string const: TechArticle description: type: string maxLength: 1600 name: type: string url: *uri-string NlwebAnswer: description: NLWeb documentation answer in a supported response format. type: object required: [_meta] properties: _meta: example: response_format: conversational_search response_type: answer version: '0.55' allOf: - $ref: '#/components/schemas/NlwebMeta' - type: object properties: response_type: { const: answer } results: example: [] type: array maxItems: 10 items: $ref: '#/components/schemas/NlwebDocumentationResult' content: example: [{ type: text, text: 'Found 1 documentation result.' }] type: array maxItems: 1 items: type: object required: [text, type] properties: text: { type: string } type: { type: string, const: text } structuredData: example: [] type: array maxItems: 10 items: $ref: '#/components/schemas/NlwebDocumentationResult' oneOf: - { required: [results], properties: { results: { type: array } } } - required: [content, structuredData] properties: content: { type: array } structuredData: { type: array } NlwebFailure: description: Typed NLWeb request or search failure. type: object required: [_meta, error] properties: _meta: example: { response_type: failure, version: '0.55' } allOf: - $ref: '#/components/schemas/NlwebMeta' - type: object properties: response_type: { const: failure } error: example: { code: INVALID_QUERY, message: 'Request is invalid.' } type: object required: [code, message] properties: code: { type: string } message: { type: string } ComposePrepareRequest: description: Inputs for preparing source-backed post guidance. type: object example: { step: compose, topic: PostgreSQL query planning } required: [step, topic] properties: step: type: string const: compose topic: type: string minLength: 1 maxLength: 25000 description: Subject for the post. example: PostgreSQL query planning goal: type: string enum: [engagement, followers, authority, conversation] default: engagement description: User goal used for 1 follow-up question. styleUsername: type: string minLength: 1 maxLength: 64 description: Username from a style analysis saved to this account. example: example_user additionalProperties: true ComposeRefineRequest: description: Inputs for refining a post plan. type: object required: [step, topic, goal, tone] properties: step: type: string const: refine topic: type: string minLength: 1 maxLength: 25000 description: Subject to refine into a post. goal: type: string enum: [engagement, followers, authority, conversation] description: User goal interpreted against published ranking signals. tone: type: string minLength: 1 maxLength: 500 description: Requested writing tone. example: professional mediaType: type: string enum: [photo, video, none] description: Planned media type. callToAction: type: string minLength: 1 maxLength: 500 description: Specific action the draft should request. additionalContext: type: string minLength: 1 maxLength: 25000 description: Audience, constraints, sources, or other writing context. additionalProperties: true ComposeScoreRequest: description: Inputs for checking a post draft. type: object required: [step, draft] properties: step: type: string const: score draft: type: string minLength: 1 maxLength: 25000 description: Full post text. The endpoint never assigns a ranking score. hasLink: type: boolean deprecated: true x-stainless-deprecation-message: Ignored. Remove this field. description: Accepted for backward compatibility. No guidance uses it. default: false hasMedia: type: boolean deprecated: true x-stainless-deprecation-message: >- Ignored. Remove this field. description: > Accepted for backward compatibility. Text checks ignore this field. additionalProperties: true ComposeContentRule: description: 1 source-backed ranking fact returned during preparation. type: object required: [rule] example: { rule: Ranking is viewer-specific. Text alone cannot predict reach. } properties: rule: type: string example: Ranking is viewer-specific. Text alone cannot predict reach. additionalProperties: false ComposeRadarRecommendation: deprecated: true description: Deprecated compatibility schema. The response array is empty. type: object required: [endpoint, guidance, source, useFor] properties: endpoint: type: string description: Radar endpoint for this source. guidance: type: string description: Source-specific drafting guidance. source: type: string enum: [ reddit, github, trustmrr, hacker_news, google_trends, wikipedia, polymarket, ] useFor: type: string description: Current-topic research this source supports. additionalProperties: false ComposeSignalLabel: description: 1 ranking signal and its source-value limit. type: object required: [action, multiplier] properties: action: type: string description: Human-readable published signal name. multiplier: type: string const: Source default. Production value can vary. additionalProperties: false ComposeScorerSignal: description: 1 source ranking signal without a production claim. type: object required: [context, signal, weight] properties: context: type: string description: Signal direction and production limit. signal: type: string description: Signal name from X's public ranking repository. weight: type: 'null' description: Null prevents source defaults becoming production claims. additionalProperties: false ComposeSavedStyle: description: A saved username style and analyzed post count. type: object required: [tweetCount, username] properties: tweetCount: *nonnegative-integer username: type: string additionalProperties: false ComposePrepareResult: description: Rules, questions, and research guidance for drafting a post. type: object required: - contentRules - engagementMultipliers - engagementVelocity - followUpQuestions - intentUrl - nextStep - radarRecommendations - scorerWeights - source - topPenalties properties: contentRules: type: array minItems: 10 maxItems: 10 items: $ref: '#/components/schemas/ComposeContentRule' description: Facts derived only from xai-org/x-algorithm. engagementMultipliers: type: array minItems: 26 maxItems: 26 items: $ref: '#/components/schemas/ComposeSignalLabel' description: > Source ranking signals. Repository defaults may vary in production. engagementVelocity: type: string description: Publication limit for timing and decay claims. followUpQuestions: type: array minItems: 4 maxItems: 4 items: type: string intentUrl: type: string format: uri description: X post intent seeded with the topic. nextStep: type: string radarRecommendations: type: array deprecated: true minItems: 0 maxItems: 0 items: $ref: '#/components/schemas/ComposeRadarRecommendation' description: Deprecated compatibility field. Always empty. scorerWeights: type: array minItems: 26 maxItems: 26 items: $ref: '#/components/schemas/ComposeScorerSignal' description: Source signals with production values withheld as null. source: type: string description: Signal source and evidence limits. topPenalties: type: array minItems: 5 maxItems: 5 items: type: string description: Negative engagement predictions in the public model. savedStyles: type: array items: $ref: '#/components/schemas/ComposeSavedStyle' description: Style analyses saved to the account. styleTweets: type: array items: type: string description: Cached examples for the requested style username. styleNote: type: string description: Next action when no cached style is available. additionalProperties: false ComposeExamplePattern: deprecated: true description: Deprecated example-pattern schema. The response array is empty. type: object required: [description, pattern] properties: description: type: string pattern: type: string additionalProperties: false ComposeRefineResult: description: Source-backed guidance for refining a post. type: object required: [compositionGuidance, examplePatterns, intentUrl, nextStep] properties: compositionGuidance: type: array items: type: string description: Request context and xai-org/x-algorithm guidance. examplePatterns: type: array deprecated: true minItems: 0 maxItems: 0 items: $ref: '#/components/schemas/ComposeExamplePattern' intentUrl: type: string format: uri description: X post intent generated for the refined topic. nextStep: type: string additionalProperties: false ComposeScoreCheck: description: 1 deterministic draft check. type: object required: [factor, passed] properties: factor: type: string passed: type: boolean suggestion: type: string description: Present only when the check fails. additionalProperties: false ComposeScoreResult: description: Posting validation without a fabricated ranking score. type: object required: [checklist, nextStep, passed, passedCount, topSuggestion, totalChecks] properties: checklist: type: array minItems: 1 maxItems: 1 items: $ref: '#/components/schemas/ComposeScoreCheck' description: Deterministic input validation. Not a reach prediction. intentUrl: type: string format: uri description: Present only when every check passes. nextStep: type: string passed: type: boolean passedCount: type: integer minimum: 0 maximum: 1 topSuggestion: type: string totalChecks: type: integer const: 1 additionalProperties: false XWriteActionBilling: type: object additionalProperties: false required: [status, charged, plannedCredits, chargedCredits] properties: status: type: string enum: [not_charged, pending, charged, charge_failed, refunded] example: charged charged: *boolean-example-true plannedCredits: &decimal-string-example type: string pattern: '^\d+$' example: '10' chargedCredits: *decimal-string-example description: > plannedCredits is the approved maximum. chargedCredits comes from the settled credit ledger. Xquik charges nothing for pending or failed writes. example: status: charged charged: true plannedCredits: '10' chargedCredits: '10' XWriteActionAccount: type: [object, 'null'] description: Connected account selected for the write. additionalProperties: false required: [id, username] properties: id: type: string username: type: string example: id: '42' username: example XWriteActionTarget: type: [object, 'null'] description: Existing X resource targeted by the write, when applicable. additionalProperties: false required: [type, id] properties: type: type: string enum: [tweet, user, community] id: type: string example: type: tweet id: '9876543210' XWriteActionRequest: type: object description: Stable fingerprint and sanitized payload for replay checks. additionalProperties: false required: [hash, payload] properties: hash: type: [string, 'null'] pattern: '^[0-9a-f]{64}$' description: Stable hash of account, action, target, and payload. payload: type: [object, 'null'] additionalProperties: true description: Exact sanitized payload dispatched for this action. example: hash: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef payload: tweet_id: '9876543210' XWriteActionResult: type: [object, 'null'] description: Confirmed result produced by the write, when available. additionalProperties: false properties: type: type: string enum: [tweet, direct_message, media, community, state_change] id: type: string state: type: string example: type: state_change id: '9876543210' state: liked XWriteActionNextAction: type: [object, 'null'] description: Exact follow-up an API client or agent should perform. additionalProperties: false required: [type] properties: type: type: string enum: [poll, retry, verify_result, fix_request] url: type: string afterMs: type: integer minimum: 0 description: Milliseconds to wait before you poll or retry. requiresNewIdempotencyKey: type: boolean example: type: poll url: /api/v1/x/write-actions/12345 afterMs: 2000 XWriteAction: type: object required: - object - id - writeActionId - action - status - terminal - retryable - safeToRetry - statusUrl - pollAfterMs - charged - chargedCredits - billing - request - account - target - targetId - result - nextAction - sendDispatched - success properties: object: type: string const: x_write_action id: type: string example: '12345' writeActionId: type: string example: '12345' action: type: string example: like enum: - create_tweet - delete_tweet - like - unlike - retweet - unretweet - follow - unfollow - remove_follower - send_dm - delete_dm - upload_media - update_profile - update_avatar - update_banner - create_community - delete_community - join_community - leave_community status: type: string example: success enum: - accepted - dispatching - pending_confirmation - success - failed - expired terminal: *boolean-example-true retryable: type: boolean description: True only when a new attempt is likely to succeed. example: false safeToRetry: type: boolean description: > True only when X did not get the write and a new idempotency key may be used. example: false statusUrl: type: string example: /api/v1/x/write-actions/12345 pollAfterMs: type: [integer, 'null'] minimum: 0 example: 1000 charged: *boolean-example-true chargedCredits: *decimal-string-example billing: $ref: '#/components/schemas/XWriteActionBilling' request: $ref: '#/components/schemas/XWriteActionRequest' account: $ref: '#/components/schemas/XWriteActionAccount' target: $ref: '#/components/schemas/XWriteActionTarget' targetId: type: [string, 'null'] example: '9876543210' result: $ref: '#/components/schemas/XWriteActionResult' nextAction: $ref: '#/components/schemas/XWriteActionNextAction' requestHash: type: string pattern: '^[0-9a-f]{64}$' example: 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef requestId: type: string example: 01JZ8R7QSC9QKT0V7JX4M2A6B8 idempotent: type: boolean description: True when this answers a retry of an earlier request with the same Idempotency-Key. example: false error: type: string example: x_write_ambiguous message: type: string example: Invalid input. Check request fields. sendDispatched: *boolean-example-true sendDispatchedAt: type: string format: date-time description: Dispatch timestamp when the write reached execution. example: '2026-07-21T05:00:00Z' createdAt: type: string format: date-time example: '2026-07-21T05:00:00Z' updatedAt: &write-completion-time-example-schema type: string format: date-time example: '2026-07-21T05:00:02Z' completedAt: *write-completion-time-example-schema expiresAt: type: string format: date-time description: > Deadline for resolving a non-terminal write. This is not the Idempotency-Key retention deadline. example: '2026-07-22T05:00:00Z' confirmedAt: *write-completion-time-example-schema confirmationCheckedAt: *write-completion-time-example-schema confirmationAttempts: type: integer minimum: 0 example: 1 tweetId: type: string description: Compatibility field for a confirmed tweet result ID. example: '9876543210' messageId: type: string description: Compatibility field for a confirmed direct message ID. example: '1234567890' mediaId: type: string description: Compatibility field for a confirmed media upload ID. example: '2345678901' mediaUrl: type: string format: uri description: Public media URL when the upload creates one. example: https://media.xquik.com/example.jpg communityId: type: string description: Compatibility field for a confirmed community ID. example: '3456789012' communityName: type: string description: Confirmed community name when available. example: Builders resultId: type: string description: Compatibility result ID for other write actions. example: '9876543210' media: type: object additionalProperties: true description: Media count, kind, size, and billing details when used. example: count: 1 kind: image details: type: object additionalProperties: true description: Structured recovery context for a failed write. example: suggestion: Poll the action status URL. success: *boolean-example-true description: > Durable write record. Poll statusUrl until terminal is true. Reusing its Idempotency-Key returns this record. Create another action only when safeToRetry is true. XWriteActionError: type: object description: Canonical pre-dispatch error with safe recovery guidance. additionalProperties: true required: - error - message - retryable - safeToRetry - charged - chargedCredits - success - nextAction properties: error: type: string example: invalid_input message: type: string example: Invalid input. Check request fields. retryable: *boolean-example-false safeToRetry: *boolean-example-true charged: *boolean-false chargedCredits: type: string const: '0' success: *boolean-false writeActionId: type: string example: '12345' statusUrl: type: string example: /api/v1/x/write-actions/12345 nextAction: $ref: '#/components/schemas/XWriteActionNextAction' allowedFields: type: array example: [account, text] items: type: string fieldErrors: type: array example: - code: required message: Account is required. path: account items: type: object required: [code, message, path] properties: code: type: string message: type: string path: type: string XWritePaymentRequired: allOf: - $ref: '#/components/schemas/XWriteAction' - type: object required: [dashboard, error, message, top_up_url] properties: dashboard: type: string const: /dashboard/account description: Dashboard page to add credits or change the plan. top_up_url: type: string const: POST /api/v1/credits/topup description: Call that creates a top-up checkout. description: > Durable failed write action with the applicable payment guidance. SupportMessageBody: description: Non-empty support message text. type: string minLength: 1 maxLength: 10000 pattern: '.*\S.*' example: 'Thank you for the update.' SupportTicketSubject: description: Non-empty support ticket subject. type: string minLength: 1 maxLength: 500 pattern: '.*\S.*' example: 'Cannot connect X account' SupportAttachmentUploads: description: 1 to 4 support image or video uploads. type: array minItems: 1 maxItems: 4 example: ['screen.png'] items: type: string format: binary maxLength: 26214400 description: Image up to 10 MiB or video up to 25 MiB. A message takes up to 30 MiB. SupportMessageSubmission: description: Support submission containing a message body. type: object required: [body] properties: body: { $ref: '#/components/schemas/SupportMessageBody' } SupportAttachmentSubmission: description: Support submission with 1 or more attachments. type: object required: [attachments] properties: attachments: { $ref: '#/components/schemas/SupportAttachmentUploads' } SupportMultipartSubmission: description: Multipart support submission with a body or attachments. anyOf: - $ref: '#/components/schemas/SupportMessageSubmission' - $ref: '#/components/schemas/SupportAttachmentSubmission' SupportTicketSubjectSubmission: description: Support submission containing a ticket subject. type: object required: [subject] properties: subject: { $ref: '#/components/schemas/SupportTicketSubject' } SupportAttachment: description: Downloadable image or video attached to a support message. type: object required: [publicId, filename, contentType, kind, sizeBytes, status, url] properties: publicId: type: string example: 'att_a1b2c3d4e5f6a1b2c3d4e5f6' filename: type: string example: 'screen.png' contentType: type: string description: Validated media type. enum: [ image/jpeg, image/png, image/gif, image/webp, video/mp4, video/quicktime, video/webm, ] kind: type: string description: Attachment media class. enum: [image, video] example: image sizeBytes: type: integer minimum: 0 format: int64 example: 204800 status: type: string description: Storage processing state. enum: [pending, ready, failed] example: ready url: type: string example: '/api/v1/support/attachments/att_a1b2c3d4e5f6a1b2c3d4e5f6' SupportAttachmentReceipt: description: Attachment identifier and initial processing state. type: object required: [publicId, status] properties: publicId: type: string example: 'att_a1b2c3d4e5f6a1b2c3d4e5f6' status: type: string enum: [pending, ready, failed] example: pending PaginatedTweets: description: > Follow next_cursor while the response reports more pages. A page can hold fewer rows than its limit & still report more. That report decides, not the row count. A page can be empty & still report more, filtered or not. Automatic search, user Tweet & reply coverage keeps shape, filters, aliases & billing. Unprefixed cursors are legacy. type: object example: tweets: - &user-tweet-example id: '2102761519985332442' text: "This galaxy is a little extra.\n\nMeet Messier 106, a spiral galaxy with an extra set of arms. These two additional arms are made of gas heated up by jets from the galaxy’s central black hole. The jets’ superheated shockwaves are depicted in royal blue by @chandraxray. https://t.co/421Lzs0r0c" retweetCount: 1364 replyCount: 271 likeCount: 9775 quoteCount: 85 viewCount: 962488 bookmarkCount: 599 conversationId: '2102761519985332442' contentDisclosure: aiGenerated: hasAiGeneratedMedia: false displayTextRange: - 0 - 267 edit: editableUntilMsecs: '1790175988000' editTweetIds: - '2102761519985332442' entities: hashtags: [] urls: [] user_mentions: - id_str: '12415722' indices: - 254 - 266 name: 'Chandra Observatory' screen_name: 'chandraxray' isNoteTweet: false isPinned: false isQuoteStatus: false isReply: false isRetweet: false isTranslatable: false lang: 'en' possiblySensitive: false source: 'Sprinklr' type: 'tweet' url: 'https://x.com/NASA/status/2102761519985332442' viewState: 'EnabledWithCount' createdAt: 'Wed Sep 23 14:06:28 +0000 2026' media: - altText: 'A spiral galaxy, laying diagonally at a three-quarters profile view. Its center is a luminous yellow that stretches out into a pinwheel of wispy blue and red arms. The disc itself is decorated with a smattering of stars and dark dust.' availabilityStatus: 'Available' displayUrl: 'pic.x.com/421Lzs0r0c' expandedUrl: 'https://x.com/NASA/status/2102761519985332442/photo/1' focusRects: - h: 1146 w: 2047 x: 0 'y': 419 - h: 1565 w: 1565 x: 0 'y': 0 - h: 1565 w: 1373 x: 0 'y': 0 - h: 1565 w: 783 x: 0 'y': 0 - h: 1565 w: 2047 x: 0 'y': 0 height: 1565 id: '2102761515958833152' indices: - 268 - 291 mediaKey: '3_2102761515958833152' mediaUrl: 'https://pbs.twimg.com/media/HS6CdTYWkAAp0e1.jpg' sizes: large: h: 1565 resize: 'fit' w: 2047 medium: h: 917 resize: 'fit' w: 1200 small: h: 520 resize: 'fit' w: 680 thumb: h: 150 resize: 'crop' w: 150 type: 'photo' url: 'https://t.co/421Lzs0r0c' width: 2047 author: id: '11348282' username: 'NASA' name: 'NASA' followers: 92376233 following: 115 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' description: 'Making the seemingly impossible, possible. ✨' location: 'Pale Blue Dot' createdAt: 'Wed Dec 19 20:20:32 +0000 2007' statusesCount: 74336 mediaCount: 28160 protected: false url: 'http://www.nasa.gov/' favouritesCount: 17003 isTranslator: false possiblySensitive: false verifiedType: 'Government' profile_bio: description: 'Making the seemingly impossible, possible. ✨' entities: description: {} url: urls: - display_url: 'nasa.gov' expanded_url: 'http://www.nasa.gov/' indices: - 0 - 23 url: 'https://t.co/9NkQJKAnuU' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'regular' superFollowEligible: false - id: '2102425682286412261' text: 'Sept. 22 marks the fall equinox. That means day and night are nearly equal in length around the world, and in the Northern Hemisphere, fall begins. In the Southern Hemisphere, spring begins on this day. https://t.co/laEQ0JajuN' retweetCount: 1258 replyCount: 200 likeCount: 7566 quoteCount: 98 viewCount: 961825 bookmarkCount: 322 conversationId: '2102425682286412261' contentDisclosure: aiGenerated: hasAiGeneratedMedia: false displayTextRange: - 0 - 202 edit: editableUntilMsecs: '1790095918000' editTweetIds: - '2102425682286412261' entities: hashtags: [] urls: [] user_mentions: [] isNoteTweet: false isPinned: false isQuoteStatus: false isReply: false isRetweet: false isTranslatable: false lang: 'en' possiblySensitive: false source: 'Sprinklr' type: 'tweet' url: 'https://x.com/NASA/status/2102425682286412261' viewState: 'EnabledWithCount' createdAt: 'Tue Sep 22 15:51:58 +0000 2026' media: - altText: "A satellite's-eye view from October 2022 of the Adirondack Mountains of northeast New York during fall. The leaves on trees are a fiery orange and red. Some trees remain green. White fluffy clouds are visible at the edges of the image." availabilityStatus: 'Available' displayUrl: 'pic.x.com/laEQ0JajuN' expandedUrl: 'https://x.com/NASA/status/2102425682286412261/photo/1' focusRects: - h: 1801 w: 3216 x: 0 'y': 1187 - h: 2988 w: 2988 x: 0 'y': 0 - h: 2988 w: 2621 x: 0 'y': 0 - h: 2988 w: 1494 x: 0 'y': 0 - h: 2988 w: 3216 x: 0 'y': 0 height: 2988 id: '2102425671280553984' indices: - 203 - 226 mediaKey: '3_2102425671280553984' mediaUrl: 'https://pbs.twimg.com/media/HS1RAkdW8AAY1Mp.jpg' sizes: large: h: 1903 resize: 'fit' w: 2048 medium: h: 1115 resize: 'fit' w: 1200 small: h: 632 resize: 'fit' w: 680 thumb: h: 150 resize: 'crop' w: 150 type: 'photo' url: 'https://t.co/laEQ0JajuN' width: 3216 author: id: '11348282' username: 'NASA' name: 'NASA' followers: 92376233 following: 115 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' description: 'Making the seemingly impossible, possible. ✨' location: 'Pale Blue Dot' createdAt: 'Wed Dec 19 20:20:32 +0000 2007' statusesCount: 74336 mediaCount: 28160 protected: false url: 'http://www.nasa.gov/' favouritesCount: 17003 isTranslator: false possiblySensitive: false verifiedType: 'Government' profile_bio: description: 'Making the seemingly impossible, possible. ✨' entities: description: {} url: urls: - display_url: 'nasa.gov' expanded_url: 'http://www.nasa.gov/' indices: - 0 - 23 url: 'https://t.co/9NkQJKAnuU' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'regular' superFollowEligible: false has_next_page: true next_cursor: 'DAAHCgABHTK6Vr___-sLAAIAAAATMjEwMTc3MDE4NjE1NjA1Mjk1OQgAAwAAAAIAAA' filtered_count: 0 required: [tweets, has_next_page, next_cursor] properties: filtered_count: *nonnegative-integer tweets: type: array items: $ref: '#/components/schemas/SearchTweet' example: - *user-tweet-example has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' readBackTo: type: string format: date-time description: > How far back a filtered Latest search has read, in UTC. Xquik checked every newer post, so an empty page still moves this time back. example: '2026-10-04T10:07:00.000Z' windowComplete: type: boolean const: true description: Present on a last page whose sources all read past its start time. example: true searchedQuery: type: string description: Search q as X ran it, when Xquik fixed it. example: 'openai gpt' searchContext: type: object description: > What X shows beside a search's posts that is the same for every reader. Present on a search for a cashtag X has a card for, such as $BTC. required: [smartTag] properties: smartTag: type: object description: X's card for the cashtag the search names. required: [id] properties: id: type: string description: The ticker X matched. example: BTC active: type: boolean description: Whether X lists the ticker as active. example: true supportsOhlc: type: boolean description: Whether X charts the ticker with open, high, low & close prices. example: false CoverageStopReason: description: Reason a coverage strategy stopped. type: string enum: - cursor_failure - deadline - exhausted - failed - page_limit - result_limit - stalled TweetSearchCoverageWindow: description: Non-overlapping time partition used by 1 strategy. type: object required: [sinceTime, untilTime] properties: sinceTime: &date-time-string type: string format: date-time untilTime: *date-time-string TweetSearchCoverageStrategy: description: Result counts and stop reason for 1 Tweet search strategy. type: object required: - duplicateCount - pagesFetched - queryType - stopReason - strategy - uniqueAdded properties: duplicateCount: *nonnegative-integer pagesFetched: *nonnegative-integer queryType: type: string enum: [Latest, Top] stopReason: $ref: '#/components/schemas/CoverageStopReason' strategy: &bounded-strategy-number type: integer minimum: 1 maximum: 8 uniqueAdded: *nonnegative-integer window: $ref: '#/components/schemas/TweetSearchCoverageWindow' CoverageDiagnosticBase: description: Shared maximum-coverage counts and completion state. type: object required: - complete - cursorFailureCount - deadlineReached - duplicateCount - failedStrategyCount - malformedCount - pagesFetched - responseTruncated - resultLimitReached - stalledStrategyCount - strategyCount properties: complete: type: boolean description: > True after all active strategies exhaust their sources. An empty read of the whole search window also ends its time slices. cursorFailureCount: *nonnegative-integer deadlineReached: type: boolean duplicateCount: *nonnegative-integer failedStrategyCount: *nonnegative-integer malformedCount: *nonnegative-integer pagesFetched: *nonnegative-integer responseTruncated: type: boolean description: True when credits or the requested limit reduce output. resultLimitReached: type: boolean stalledStrategyCount: *nonnegative-integer strategyCount: *bounded-strategy-number TweetSearchCoverageDiagnostic: description: Coverage evidence across parallel search strategies. allOf: - $ref: '#/components/schemas/CoverageDiagnosticBase' - type: object required: [partitioned, returnedTweets, strategies, uniqueTweets] properties: partitioned: type: boolean description: Whether bounded time windows ran in parallel. returnedTweets: &bounded-result-count type: integer minimum: 0 maximum: 10000 strategies: type: array items: $ref: '#/components/schemas/TweetSearchCoverageStrategy' uniqueTweets: *bounded-result-count TweetSearchCoverageResponse: description: Terminal Tweet search coverage response with diagnostics. allOf: - $ref: '#/components/schemas/PaginatedTweets' - type: object required: [diagnostic] properties: has_next_page: *boolean-false next_cursor: type: string const: '' diagnostic: $ref: '#/components/schemas/TweetSearchCoverageDiagnostic' TweetReplies: description: > Direct reply rows. Requests without mode use resumable automatic coverage. Complete mode also returns nested replies and coverage diagnostics. example: tweets: - id: '2083169393878684056' text: '@OpenAI A model optimizing its own serving cost after deployment is a neat flywheel to see in production ⚙️' retweetCount: 0 replyCount: 0 likeCount: 1 quoteCount: 0 viewCount: 473 bookmarkCount: 1 conversationId: '2082577277246972300' displayTextRange: - 8 - 107 edit: editableUntilMsecs: '1785504861000' editTweetIds: - '2083169393878684056' entities: hashtags: [] urls: [] user_mentions: - id_str: '4398626122' indices: - 0 - 7 name: 'OpenAI' screen_name: 'OpenAI' inReplyToId: '2082577277246972300' inReplyToUserId: '4398626122' inReplyToUsername: 'OpenAI' isNoteTweet: false isPinned: false isQuoteStatus: false isReply: true isRetweet: false isTranslatable: false lang: 'en' source: 'Twitter Web App' type: 'reply' url: 'https://x.com/PublicAI_/status/2083169393878684056' viewState: 'EnabledWithCount' hasCommunityNotes: false createdAt: 'Fri Jul 31 12:34:21 +0000 2026' author: id: '1615238618301501440' username: 'PublicAI_' name: 'PublicAI' followers: 210053 following: 173 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1936462795584729088/c3advPaX_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/1615238618301501440/1744434414' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/1615238618301501440/1744434414' description: 'AI data research lab. We ship products that collect real human work for models. Backed by @StanfordSBA. PublicAI LLM Index @PublicAIData.' location: 'Mars' createdAt: 'Tue Jan 17 06:44:40 +0000 2023' statusesCount: 2936 mediaCount: 535 protected: false url: 'http://PublicAi.io' favouritesCount: 3726 isTranslator: false possiblySensitive: false pinnedTweetIds: - '2092582845722292633' verifiedType: 'Blue' profile_bio: description: 'AI data research lab. We ship products that collect real human work for models. Backed by @StanfordSBA. PublicAI LLM Index @PublicAIData.' entities: description: {} url: urls: - display_url: 'PublicAi.io' expanded_url: 'http://PublicAi.io' indices: - 0 - 23 url: 'https://t.co/4HO9Tpo2aA' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' professional: category: - icon_name: 'IconBriefcaseStroke' id: 713 name: 'Science & Technology' professional_type: 'Business' rest_id: '1856812443324092849' profileDescriptionLanguage: 'en' profileImageShape: 'Circle' profileTranslatorType: 'none' superFollowEligible: false - id: '2082911177416568983' text: '@OpenAI Cheaper, faster, better' retweetCount: 0 replyCount: 0 likeCount: 2 quoteCount: 0 viewCount: 1072 bookmarkCount: 0 conversationId: '2082577277246972300' displayTextRange: - 8 - 31 edit: editableUntilMsecs: '1785443297000' editTweetIds: - '2082911177416568983' entities: hashtags: [] urls: [] user_mentions: - id_str: '4398626122' indices: - 0 - 7 name: 'OpenAI' screen_name: 'OpenAI' inReplyToId: '2082577277246972300' inReplyToUserId: '4398626122' inReplyToUsername: 'OpenAI' isNoteTweet: false isPinned: false isQuoteStatus: false isReply: true isRetweet: false isTranslatable: false lang: 'en' source: 'Twitter Web App' type: 'reply' url: 'https://x.com/Wager_Predict/status/2082911177416568983' viewState: 'EnabledWithCount' hasCommunityNotes: false createdAt: 'Thu Jul 30 19:28:17 +0000 2026' author: id: '1513781916990083073' username: 'Wager_Predict' name: 'Wager Predict' followers: 54048 following: 76 verified: true isBlueVerified: false isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/2076634676228407298/O2FJ2EIM_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/1513781916990083073/1784142396' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/1513781916990083073/1784142396' description: "Trade on what happens next. | The Markets are brewing Up.\nTGE soon!" createdAt: 'Tue Apr 12 07:32:01 +0000 2022' statusesCount: 1918 mediaCount: 280 protected: false url: 'http://wagerpredict.com' favouritesCount: 1360 isTranslator: false possiblySensitive: false pinnedTweetIds: - '2077051650754367854' verifiedType: 'Business' profile_bio: description: "Trade on what happens next. | The Markets are brewing Up.\nTGE soon!" entities: description: {} url: urls: - display_url: 'wagerpredict.com' expanded_url: 'http://wagerpredict.com' indices: - 0 - 23 url: 'https://t.co/1MgjWEdMLw' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' professional: category: [] professional_type: 'Business' rest_id: '1560458726439788544' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'none' superFollowEligible: false has_next_page: true next_cursor: 'xqcv1_tkGoEx1UJRqeog9a2BJdmzUZTMCoU_M8kb6ZZwaDFa0.1' filtered_count: 0 allOf: - $ref: '#/components/schemas/PaginatedTweets' - type: object properties: tweets: type: array items: $ref: '#/components/schemas/ReplyTweet' nested_replies: type: array items: $ref: '#/components/schemas/ReplyTweet' description: Nested replies. Excluded from direct coverage. diagnostic: $ref: '#/components/schemas/ReplyCoverageDiagnostic' limit_reached: type: boolean const: true description: Present when your limit cut a complete-mode answer. The post has more replies. Raise limit to get them all. example: true orderPartial: type: boolean const: true description: Present with latest or oldest sort. The read stopped before it held every reply X shows. Rows stay sorted by date, but replies may be missing between them. Retry later for a gap-free order. Complete mode and automatic pages set it alike. example: true hiddenReplies: type: integer minimum: 1 description: Present on the last automatic page, and on a complete-mode answer without rows. X counts this many more replies but shows them to nobody. They may be hidden, protected or deleted. A retry returns the same replies. example: 1 partialBefore: type: string format: date-time description: Present on an answer that lacks replies of a large thread posted before this time. X shows only part of the replies older than 7 days. A retry returns about the same replies. example: '2026-10-07T00:00:00.000Z' message: type: string description: Explains an answer cut by your limit. example: The post has more matching replies than limit. Raise limit to get them all. IncompleteTweetReplies: description: Partial reply results with a safe diagnostic. allOf: - $ref: '#/components/schemas/TweetReplies' - type: object required: [error, message, nested_replies, diagnostic] properties: error: type: string const: replies_incomplete message: type: string has_next_page: *boolean-false next_cursor: type: string const: '' ReplyCoverageStrategy: description: Reply counts & stop reason per strategy. type: object required: - name - pagesAttempted - newDirectReplies - newNestedReplies - stopReason properties: name: type: string pagesAttempted: *nonnegative-integer newDirectReplies: *nonnegative-integer newDirectReplyPages: type: array description: > For a search of the post's conversation, the page that listed each new direct reply, from 1. items: type: integer minimum: 1 newNestedReplies: *nonnegative-integer stopReason: type: string enum: - deadline - empty_pages - error - missing_cursor - no_next_page - page_cap - partial_view - repeated_cursor - window_covered - window_passed ReplyCoverageRichness: description: Field counts across collected direct replies. type: object required: - totalReplies - text - author - createdAt - language - url - entities - media - article - card - communityNote - quotedOrRepostedTweet - engagementCounts properties: totalReplies: type: integer minimum: 0 description: Unique direct replies evaluated. text: type: integer minimum: 0 description: Replies with text. author: type: integer minimum: 0 description: Replies with author details. createdAt: type: integer minimum: 0 description: Replies with creation timestamps. language: type: integer minimum: 0 description: Replies with language. url: type: integer minimum: 0 description: Replies with canonical URLs. entities: type: integer minimum: 0 description: Replies with entities. media: type: integer minimum: 0 description: Replies with media. article: type: integer minimum: 0 description: Replies with articles. card: type: integer minimum: 0 description: Replies with cards. communityNote: type: integer minimum: 0 description: Replies with community notes. quotedOrRepostedTweet: type: integer minimum: 0 description: Replies with quotes or reposts. engagementCounts: type: integer minimum: 0 description: Replies with engagement counts. ReplyCoverageDiagnostic: description: Direct-reply coverage & collection evidence. type: object required: - complete - reportedReplyCount - targetDirectReplies - uniqueDirectReplies - coveragePercentage - nestedReplyCount - pagesAttempted - strategiesAttempted - duplicateCount - cursorFailures - repeatedCursorCount - emptyFalseProgressPages - malformedCount - unrelatedCount - missingResponseModulesOrFields - recommendedFallback - richness - responseTruncated - sourcesEnded properties: complete: type: boolean description: Coverage met its target, or read the whole time window, without truncation. Protected accounts' replies count but aren't returned. replyTreeComplete: type: boolean description: All child counts are known & match collected replies. replyScopeComplete: type: boolean description: Replies are accounted for through the requested scope & depth. Source errors remain separate. reportedReplyCount: type: integer minimum: 0 description: Source post reply count. targetDirectReplies: type: integer minimum: 0 description: Direct replies required to meet the target. uniqueDirectReplies: type: integer minimum: 0 description: Unique direct replies to the source post. coveragePercentage: type: number minimum: 0 maximum: 100 description: Unique direct replies divided by the reported count, as a percentage. nestedReplyCount: type: integer minimum: 0 description: Unique nested replies, excluded from direct coverage. pagesAttempted: type: integer minimum: 0 description: Pages attempted across strategies. strategiesAttempted: type: array description: Pagination & contribution evidence per strategy. items: $ref: '#/components/schemas/ReplyCoverageStrategy' duplicateCount: type: integer minimum: 0 description: Duplicate IDs removed across pages & strategies. cursorFailures: type: integer minimum: 0 description: Cursor requests that failed. repeatedCursorCount: type: integer minimum: 0 description: Looping cursors rejected. emptyFalseProgressPages: type: integer minimum: 0 description: Empty pages rejected for no progress. malformedCount: type: integer minimum: 0 description: Malformed response items rejected. unrelatedCount: type: integer minimum: 0 description: Tweets rejected from other conversations. missingResponseModulesOrFields: type: array description: Expected X modules or fields missing. items: type: string recommendedFallback: type: string description: Recommended next action when coverage is incomplete. richness: $ref: '#/components/schemas/ReplyCoverageRichness' responseTruncated: type: boolean description: Requested row limit truncated safe results. sourcesEnded: type: boolean description: Every source ended, or no reply view shows a reply. A retry returns the same rows. PaginatedUserIds: description: > A page of user IDs without profiles. Follow next_cursor while the response reports more pages. type: object example: ids: ['9876543210', '44196397'] has_next_page: true next_cursor: '1878079982871151535' required: [ids, has_next_page, next_cursor] properties: ids: type: array description: X user IDs, newest relationship first. items: type: string example: ['9876543210', '44196397'] has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' PaginatedUsers: description: > Profile coverage preserves shape, billing, aliases, and filters. Follow next_cursor while the response reports more pages. Unprefixed cursors remain legacy. type: object example: users: - &similar-user-example id: '34743251' username: 'SpaceX' name: 'SpaceX' followers: 41936873 following: 127 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1697749409851985920/HbrI04tM_normal.jpg' profilePictureOriginal: 'https://pbs.twimg.com/profile_images/1697749409851985920/HbrI04tM.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/34743251/1681251194' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/34743251/1681251194' description: "SpaceX designs, manufactures and launches the world's most advanced rockets and spacecraft" location: 'Earth' createdAt: 'Thu Apr 23 21:53:30 +0000 2009' statusesCount: 11834 mediaCount: 4713 protected: false url: 'http://spacex.com' contactInfo: links: - url: 'http://spacex.com' network: website source: url favouritesCount: 529 possiblySensitive: false pinnedTweetIds: - '2104354931595423762' verifiedType: 'Business' profile_bio: description: "SpaceX designs, manufactures and launches the world's most advanced rockets and spacecraft" entities: description: {} url: urls: - display_url: 'spacex.com' expanded_url: 'http://spacex.com' indices: - 0 - 23 url: 'https://t.co/VOJ6qEctND' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' professional: category: [] professional_type: 'Business' rest_id: '1681839322029502464' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'none' superFollowEligible: false - id: '20536157' username: 'Google' name: 'Google' followers: 31909314 following: 298 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/2042749771337564160/AgOFPEL3_normal.jpg' profilePictureOriginal: 'https://pbs.twimg.com/profile_images/2042749771337564160/AgOFPEL3.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/20536157/1780004508' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/20536157/1780004508' description: 'Here to help.' location: 'Mountain View, CA' createdAt: 'Tue Feb 10 19:14:39 +0000 2009' statusesCount: 251787 mediaCount: 38271 protected: false url: 'https://blog.google/newsletter-subscribe/' contactInfo: links: - url: 'https://blog.google/newsletter-subscribe/' network: website source: url favouritesCount: 5327 possiblySensitive: false pinnedTweetIds: - '2105388143902175529' verifiedType: 'Business' profile_bio: description: 'Here to help.' entities: description: {} url: urls: - display_url: 'blog.google/newsletter-sub…' expanded_url: 'https://blog.google/newsletter-subscribe/' indices: - 0 - 23 url: 'https://t.co/RS3iU87BGe' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' professional: category: - icon_name: 'IconBriefcaseStroke' id: 713 name: 'Science & Technology' professional_type: 'Business' rest_id: '1504886752259059716' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'regular' superFollowEligible: false has_next_page: false next_cursor: '' required: [users, has_next_page, next_cursor] properties: filtered_count: *nonnegative-integer users: &public-user-results type: array items: $ref: '#/components/schemas/UserProfile' example: - *similar-user-example has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' SearchSuggestions: description: > What X suggests for a partial search query. Each list keeps X's order. A list is empty when X suggests none of its type or types leaves it out. type: object required: [query, users, topics, hashtags, cashtags, count] example: query: nasa users: - id: '11348282' username: NASA name: NASA verified: true isBlueVerified: true isVerified: false verifiedType: Government protected: false location: Pale Blue Dot profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' badges: [] isPersonaMediaGenable: false score: 0 tokens: [] inline: false topics: - topic: nasa score: 0 tokens: [] inline: false hashtags: [] cashtags: [] count: 2 properties: query: type: string description: The query you sent, trimmed. example: nasa users: type: array description: Suggested accounts. items: $ref: '#/components/schemas/SearchSuggestionUser' topics: type: array description: Suggested search phrases that are not hashtags. items: $ref: '#/components/schemas/SearchSuggestionTopic' hashtags: type: array description: Suggested hashtags. items: $ref: '#/components/schemas/SearchSuggestionHashtag' cashtags: type: array description: Suggested stocks & crypto tokens. items: $ref: '#/components/schemas/SearchSuggestionCashtag' count: type: integer minimum: 0 description: Suggestions returned across all 4 lists. Each costs 1 credit. example: 2 SearchSuggestionUser: description: An account X suggests for the query. type: object required: [id, username, name] properties: id: type: string description: X user ID. example: '11348282' username: type: string description: Handle without the @. example: NASA name: type: string description: Display name. example: NASA verified: type: boolean description: Whether X shows any verification badge. example: true isBlueVerified: type: boolean description: Whether X shows a blue verification badge. example: true isVerified: type: boolean description: Whether the account holds X's legacy verification. example: false verifiedType: type: string description: Verification category, such as Government or Business. Omitted when X names none. example: Government protected: type: boolean description: Whether the account protects its posts. example: false location: type: string description: Public profile location text. Omitted when empty. example: Pale Blue Dot profilePicture: type: string format: uri description: Avatar URL. example: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' profilePictureOriginal: type: string format: uri description: The same avatar at full size. example: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB.jpg' badges: type: array description: Affiliation badges X shows beside the name. items: type: object description: 1 affiliation badge. properties: badgeType: type: string description: Kind of badge. example: BusinessLabel badgeUrl: type: string format: uri description: Badge image URL. example: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_bigger.jpg' description: type: string description: Name of the affiliated account. example: NASA isPersonaMediaGenable: type: boolean description: X's flag for whether media can be generated from this account's persona. example: false score: type: number description: X's rounded relevance score for the account. example: 0 tokens: type: array description: Normalized text tokens X matches the account by. items: type: string example: nasa example: [] inline: type: boolean description: X's inline flag for the account. example: false SearchSuggestionTopic: description: A search phrase X suggests for the query. type: object required: [topic] properties: topic: type: string description: Suggested search phrase. example: nasa xolane program score: type: number description: X's rounded relevance score for the phrase. example: 0 tokens: type: array description: Normalized text tokens X matches the phrase by. items: type: string example: nasa example: [] inline: type: boolean description: X's inline flag for the phrase. example: false SearchSuggestionHashtag: description: A hashtag X suggests for the query. type: object required: [hashtag] properties: hashtag: type: string description: 'Suggested hashtag, with its leading #.' example: '#nasuanimalkingdom' score: type: number description: X's rounded relevance score for the hashtag. example: 600 tokens: type: array description: Normalized text tokens X matches the hashtag by. items: type: string example: '#nasuanimalkingdom' example: ['#nasuanimalkingdom'] inline: type: boolean description: X's inline flag for the hashtag. example: false SearchSuggestionCashtag: description: A stock or crypto token X suggests for the query. type: object required: [ticker] properties: ticker: type: string description: Ticker symbol without the $. example: TSLA name: type: string description: Company or token name. example: Tesla Inc smartTag: type: string description: X's tag for the asset. $TICKER for a stock, chain:contract for a token. example: $TSLA currency: type: string description: Currency of price & marketCap. example: USD price: type: string description: Latest price as decimal text, which keeps every digit. example: '370.589999999' marketCap: type: string description: Market capitalization as decimal text. example: '1463662787286.778808593' dailyChangePercent: type: number description: Price change over the last 24 hours, in percent. example: 4.6539 logoUrl: type: string format: uri description: Logo image URL. example: 'https://abs.twimg.com/finance/v1/stock/TSLA.png' exchangeShortName: type: string description: Stock exchange. Stocks only. example: NASDAQ contractAddress: type: string description: Token contract address. Tokens only. example: '0x322f0929c4625ed5bad873c95208d54e1c003b2d' chainLogoUrl: type: string format: uri description: Logo of the token's chain. Tokens only. example: 'https://abs.twimg.com/finance/v1/crypto/robinhood/native.png' XListBanner: description: Banner image of an X List. type: object required: [url] example: url: 'https://pbs.twimg.com/media/GkIQyCGWYAA4UdW.png' width: 1125 height: 375 properties: url: { type: string, description: Banner image URL. } width: { type: integer, minimum: 0, description: Banner width in pixels. } height: { type: integer, minimum: 0, description: Banner height in pixels. } salientRect: type: object description: Area X marks as the subject of the banner, in pixels. properties: left: type: integer minimum: 0 description: Pixels from the banner's left. top: type: integer minimum: 0 description: Pixels from the banner's top. width: type: integer minimum: 0 description: Width of the marked area. height: type: integer minimum: 0 description: Height of the marked area. mediaId: { type: string, description: Media ID of an uploaded banner. } mediaKey: { type: string, description: Stable media key of an uploaded banner. } palette: type: array description: Dominant colors of an uploaded banner and their shares. items: type: object properties: percentage: type: number minimum: 0 maximum: 100 description: Share of the banner, from 0 to 100. rgb: type: object description: The color's red, green and blue values. properties: red: { type: integer, minimum: 0, maximum: 255 } green: { type: integer, minimum: 0, maximum: 255 } blue: { type: integer, minimum: 0, maximum: 255 } XList: description: > Public X List with its owner's public profile. Leaves out what X tells the reading account, such as whether it follows the List. type: object required: [id, name] example: id: '4143408' name: 'NASA Centers' description: 'NASA has 10 centers http://www.nasa.gov/about/sites' memberCount: 11 subscriberCount: 859 owner: id: '11348282' username: 'NASA' name: 'NASA' followers: 92379503 following: 115 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' description: 'Making the seemingly impossible, possible. ✨' location: 'Pale Blue Dot' createdAt: 'Wed Dec 19 20:20:32 +0000 2007' statusesCount: 74372 mediaCount: 28176 protected: false url: 'http://www.nasa.gov/' favouritesCount: 17012 possiblySensitive: false verifiedType: 'Government' profile_bio: description: 'Making the seemingly impossible, possible. ✨' entities: description: {} url: urls: - display_url: 'nasa.gov' expanded_url: 'http://www.nasa.gov/' indices: - 0 - 23 url: 'https://t.co/9NkQJKAnuU' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'regular' superFollowEligible: false url: 'https://x.com/i/lists/4143408' createdAt: '2009-12-02T22:41:02.000Z' defaultBanner: height: 375 salientRect: height: 1 left: 562 top: 187 width: 1 url: 'https://pbs.twimg.com/media/GkIOx3HW4AAHAs6.png' width: 1125 membersContext: '11 members' properties: id: { type: string, description: Numeric ID of the List. } name: { type: string, description: Name the owner gave the List. } description: type: string description: About text of the List. Empty when the owner wrote none. memberCount: { type: integer, minimum: 0, description: Accounts on the List. } subscriberCount: type: integer minimum: 0 description: Accounts that follow the List, which X calls followers. owner: type: object $ref: '#/components/schemas/UserProfile' description: Public profile of the account that owns the List. url: { type: string, description: List page on x.com. } createdAt: type: string format: date-time description: When the owner made the List. bannerUrl: type: string description: > URL of the banner the owner uploaded. Absent when the owner uploaded none. customBanner: type: object $ref: '#/components/schemas/XListBanner' description: Banner the owner uploaded. defaultBanner: type: object $ref: '#/components/schemas/XListBanner' description: > Banner X shows when the owner uploaded none. X picks it per reading account, so 2 calls can return different ones. facepileUrls: type: array description: Avatar URLs of a few List members, which X may pick per request. items: { type: string } membersContext: type: string description: Member count as X words it, such as 35 members. PaginatedLists: description: > 1 page of public X Lists. Follow next_cursor while the response reports more pages. Each returned List costs 1 credit. type: object example: { lists: [], has_next_page: false, next_cursor: '' } required: [lists, has_next_page, next_cursor] properties: lists: type: array items: $ref: '#/components/schemas/XList' has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' UserListCoverageStrategy: description: Result counts and stop reason for 1 relationship strategy. type: object required: - duplicateCount - pagesFetched - stopReason - strategy - uniqueAdded properties: duplicateCount: *nonnegative-integer pagesFetched: *nonnegative-integer stopReason: $ref: '#/components/schemas/CoverageStopReason' strategy: *bounded-strategy-number uniqueAdded: *nonnegative-integer UserListCoverageDiagnostic: description: Coverage evidence across parallel relationship strategies. allOf: - $ref: '#/components/schemas/CoverageDiagnosticBase' - type: object required: [returnedUsers, strategies, uniqueUsers] properties: returnedUsers: *bounded-result-count strategies: type: array items: $ref: '#/components/schemas/UserListCoverageStrategy' uniqueUsers: *bounded-result-count UserListCoverageResponse: description: Terminal relationship coverage response with diagnostics. allOf: - $ref: '#/components/schemas/PaginatedUsers' - type: object required: [diagnostic] properties: has_next_page: *boolean-false next_cursor: type: string const: '' diagnostic: $ref: '#/components/schemas/UserListCoverageDiagnostic' UserListScanLimit: description: > Present on the last page of a filtered automatic read that sent no maxScan, once the list scanned 100,000 profiles across its pages. That page is the list's last. type: object required: [limit, rowsRead, message] properties: limit: type: integer const: 100000 description: The profiles a filtered read scans of a list without maxScan. rowsRead: type: integer minimum: 100000 description: > Profiles the list read across its pages, kept or dropped by the filters. The last page may read past the limit. example: 100000 message: type: string description: What stopped the list & how to read further. example: Stopped at the scan limit of 100,000 profiles. Read the list again with a higher maxScan to read further. UserListPage: description: A relationship page. A filtered read's last page may name the scan limit that ended it. allOf: - $ref: '#/components/schemas/PaginatedUsers' - type: object properties: scanLimit: $ref: '#/components/schemas/UserListScanLimit' UserListResult: description: A standard or terminal maximum-coverage relationship page. example: { users: [], has_next_page: false, next_cursor: '' } oneOf: - $ref: '#/components/schemas/UserListPage' - $ref: '#/components/schemas/UserListCoverageResponse' BatchUsers: description: > Batch lookup preserves first-seen order and ignores duplicates. The ID lists name the requested IDs or usernames. They name a profile link by its username. type: object required: [ users, has_next_page, next_cursor, requested_count, processed_count, returned_count, unavailable_ids, failed_ids, unprocessed_ids, ] properties: filtered_count: type: integer minimum: 0 description: Profiles rejected by the requested filters. example: 0 users: *public-user-results has_next_page: type: boolean const: false description: Batch lookups never paginate. next_cursor: type: string description: Empty because batch lookups never paginate. maxLength: 0 example: '' requested_count: type: integer minimum: 0 maximum: 100 description: Number of unique IDs requested. example: 2 processed_count: type: integer minimum: 0 maximum: 100 description: Number of requested IDs included in the lookup. example: 2 returned_count: type: integer minimum: 0 maximum: 100 description: Number of user profiles returned and charged. example: 1 unavailable_ids: type: array description: Processed IDs with no profile on X, in first-seen request order. items: &batch-user-id type: string pattern: '^(?:\d+|[A-Za-z0-9_]{1,15})$' example: ['1234567890'] failed_ids: type: array description: Processed IDs that failed to load, in first-seen request order. They cost nothing. Retry them. items: *batch-user-id example: [] unprocessed_ids: type: array description: Requested IDs skipped because your credits ran out. Retry them after adding credits. items: *batch-user-id example: [] BatchUserTweets: description: > Each user's newest posts, in the order the users were named, with the pinned post first. The ID lists name the requested IDs or usernames. They name a profile link by its username. type: object required: [tweets, has_next_page, next_cursor, unavailable_ids, unprocessed_ids] properties: tweets: type: array items: $ref: '#/components/schemas/SearchTweet' example: *example-launch-tweets has_next_page: type: boolean const: false description: Always false. The answer holds every post in 1 page. next_cursor: type: string description: Always empty. The answer holds every post in 1 page. maxLength: 0 example: '' unavailable_ids: type: array description: Users with no account on X or with protected posts, in first-seen request order. They cost nothing. items: *batch-user-id example: ['1234567890'] unprocessed_ids: type: array description: Users the call did not read, in first-seen request order. Their read failed, the call ran out of time or credits ran out. They cost nothing. Send them again. items: *batch-user-id example: [] GuestWalletAmount: description: Confirmed USD amount for a guest wallet purchase. type: object additionalProperties: false required: [amount_minor, currency] properties: amount_minor: type: integer minimum: 1000 maximum: 25000 description: USD amount in cents. Accepted range is $10-$250. example: 1000 currency: type: string const: usd GuestWalletAmountBounds: description: Accepted guest wallet purchase range in USD cents. type: object additionalProperties: false required: [currency, maximum_minor, minimum_minor] properties: currency: type: string const: usd maximum_minor: type: integer const: 25000 minimum_minor: type: integer const: 1000 GuestWalletPurchaseRequest: description: User-confirmed guest wallet checkout request. type: object additionalProperties: false required: [amount_minor, currency] properties: amount_minor: type: integer minimum: 1000 maximum: 25000 description: USD cents accepted for this checkout. example: 1000 currency: type: string const: usd GuestWalletCheckoutResponse: description: Pending hosted checkout and guest wallet purchase details. type: object additionalProperties: false required: - account_required - amount - checkout_url - credits - expires_at - instructions - poll_after_seconds - purchase_id - requires_user_interaction - status - status_url - wallet_id properties: account_required: *boolean-false amount: $ref: '#/components/schemas/GuestWalletAmount' api_key: type: string format: password description: > Paid-read bearer credential returned only by initial creation. Store it as a secret. Never place it in a URL or log. example: xq_example_returned_once authorization: type: object additionalProperties: false required: [header, scheme] properties: header: type: string enum: [Authorization] example: Authorization scheme: type: string enum: [Bearer] example: Bearer checkout_url: type: string format: uri description: Hosted checkout URL for user interaction. example: https://checkout.example/guest/example credits: type: string pattern: '^\d+$' description: Credits granted after verified payment. example: '66666' credential_notice: type: string const: Store api_key and the Idempotency-Key securely before sharing checkout_url. No email recovery is available. expires_at: type: string format: date-time description: Time when the pending checkout expires. example: '2026-07-13T13:00:00.000Z' instructions: type: string description: Hosted checkout and status polling instructions. poll_after_seconds: type: integer const: 2 description: Wait at least this long before polling status_url. purchase_id: type: string pattern: '^gp_[A-Za-z0-9_-]+$' example: gp_example requires_user_interaction: *boolean-true status: type: string enum: [creating, pending, paid, expired, failed, refunded, disputed] example: pending status_url: type: string format: uri const: https://xquik.com/api/v1/guest-wallets/status wallet_id: type: string pattern: '^gw_[A-Za-z0-9_-]+$' example: gw_example GuestWalletCreateResponse: description: Initial guest wallet response containing the one-time key. allOf: - $ref: '#/components/schemas/GuestWalletCheckoutResponse' - type: object required: [api_key, authorization, credential_notice] GuestWalletTopupResponse: description: Existing guest wallet top-up response without a new key. allOf: - $ref: '#/components/schemas/GuestWalletCheckoutResponse' - not: anyOf: - type: object properties: api_key: type: string required: [api_key] - type: object properties: authorization: type: object required: [authorization] GuestWalletPurchaseStatus: description: Latest guest wallet purchase fulfillment state. type: object additionalProperties: false required: [amount, checkout_url, credits, expires_at, purchase_id, status] properties: amount: $ref: '#/components/schemas/GuestWalletAmount' checkout_url: anyOf: - type: string format: uri - type: 'null' description: Present only while the purchase is pending. example: https://checkout.xquik.com/session/example credits: type: string pattern: '^\d+$' example: '66666' expires_at: type: string format: date-time example: '2026-07-13T13:00:00.000Z' purchase_id: type: string pattern: '^gp_[A-Za-z0-9_-]+$' example: gp_example status: type: string enum: [creating, pending, paid, expired, failed, refunded, disputed] example: paid GuestWalletStatusResponse: description: Current balance, usability, and latest guest purchase state. type: object additionalProperties: false required: - balance - latest_purchase - poll_after_seconds - scope - status - top_up - usable - wallet_id properties: balance: type: string pattern: '^\d+$' example: '66666' latest_purchase: description: Latest purchase state. This does not determine usability. anyOf: - $ref: '#/components/schemas/GuestWalletPurchaseStatus' - type: 'null' example: amount: { amount_minor: 1000, currency: usd } checkout_url: null credits: '66666' expires_at: '2026-07-13T13:00:00.000Z' purchase_id: gp_example status: paid poll_after_seconds: description: Polling delay while payment is pending. Null means stop. anyOf: - type: integer const: 2 - type: 'null' example: 2 scope: type: string const: paid_reads status: type: string description: > Combined wallet and pending-checkout state. A pending top-up can coexist with usable true. Terminal expired or failed states require a new guest wallet. enum: [active, pending, expired, failed, frozen, closed] example: active top_up: description: Top-up action when usable and no checkout is pending. anyOf: - type: object additionalProperties: false required: [method, path] properties: method: &post-method type: string const: POST path: type: string const: /api/v1/guest-wallets/topups - type: 'null' example: method: POST path: /api/v1/guest-wallets/topups usable: type: boolean description: Whether paid reads can run. Use it instead of status. example: true wallet_id: type: string pattern: '^gw_[A-Za-z0-9_-]+$' example: gw_example GuestWalletCreateCheckoutAction: description: Explicit direct REST action for a new guest wallet checkout. type: object additionalProperties: false required: &guest-checkout-required-fields - account_required - amount_bounds - body - creates - method - path - provider - required_headers - requires_authentication - requires_user_confirmation - requires_user_interaction - response_fields - response_url_field properties: account_required: *boolean-false amount_bounds: $ref: '#/components/schemas/GuestWalletAmountBounds' body: $ref: '#/components/schemas/GuestWalletPurchaseRequest' creates: &checkout-url-field type: string const: checkout_url method: *post-method path: type: string const: /api/v1/guest-wallets provider: &legacy-checkout-provider type: string deprecated: true const: stripe required_headers: &checkout-idempotency-headers type: object additionalProperties: false required: [Idempotency-Key] properties: Idempotency-Key: type: string const: requires_authentication: *boolean-false requires_user_confirmation: *boolean-true requires_user_interaction: *boolean-true response_fields: type: array minItems: 3 maxItems: 3 prefixItems: - type: string const: checkout_url - type: string const: api_key - type: string const: status_url items: type: string enum: [checkout_url, api_key, status_url] response_url_field: *checkout-url-field GuestWalletTopupCheckoutAction: description: Explicit direct REST action for a guest wallet top-up. type: object additionalProperties: false required: *guest-checkout-required-fields properties: account_required: *boolean-false amount_bounds: $ref: '#/components/schemas/GuestWalletAmountBounds' body: $ref: '#/components/schemas/GuestWalletPurchaseRequest' creates: *checkout-url-field method: *post-method path: type: string const: /api/v1/guest-wallets/topups provider: *legacy-checkout-provider required_headers: *checkout-idempotency-headers requires_authentication: *boolean-true requires_user_confirmation: *boolean-true requires_user_interaction: *boolean-true response_fields: type: array minItems: 2 maxItems: 2 prefixItems: - type: string const: checkout_url - type: string const: status_url items: type: string enum: [checkout_url, status_url] response_url_field: *checkout-url-field AnonymousGuestAuthenticationRequired: description: > Authentication error for a non-MPP anonymous paid read. The response also offers an optional accountless checkout after confirmation. type: object additionalProperties: false required: - account_required - error - message - next_step - payment_options properties: account_required: *boolean-false error: type: string const: unauthenticated message: type: string example: Authentication required. next_step: type: string const: Ask the user to confirm a USD amount before creating checkout. payment_options: &guest-payment-options $ref: '#/components/schemas/GuestPaymentOptions' GuestPaymentRequired: description: > Credit error for a paid-read guest key with only its accountless guest top-up action. type: object additionalProperties: false required: - balance - error - message - next_step - payment_options - required - top_up_endpoint - top_up_url properties: balance: type: string pattern: '^\d+$' example: '0' error: &credit-access-error-schema type: string enum: - insufficient_credits - no_credits - no_subscription - subscription_inactive example: insufficient_credits message: type: string example: Insufficient credits. Top up or subscribe to continue. next_step: type: string const: Ask the user to confirm a USD amount before creating checkout. payment_options: type: object additionalProperties: false required: [credits] properties: credits: type: object additionalProperties: false required: [create_checkout] properties: create_checkout: $ref: '#/components/schemas/GuestWalletTopupCheckoutAction' required: type: string pattern: '^\d+$' example: '1' top_up_endpoint: type: string const: /api/v1/guest-wallets/topups top_up_url: type: string const: POST /api/v1/guest-wallets/topups AuthenticatedPaymentRequired: description: Authenticated credit or subscription error with confirmation-gated hosted checkout actions. A caller on a plan, including one whose payment failed, gets no subscription option. A key that reads only cannot open checkout, so it gets the account page as its next step and no payment_options, top_up_endpoint or top_up_url. type: object additionalProperties: false required: - balance - dashboard - error - message - next_step - required properties: balance: type: string pattern: '^\d+$' description: Available credits as a decimal string. example: '0' credits_renew_at: type: string format: date-time description: When the caller's active plan renews and grants its next credits. Present only for a plan that renews. example: '2026-10-10T08:30:00.000Z' dashboard: type: string const: /dashboard/account description: Account page for manual billing management. error: *credit-access-error-schema message: type: string description: What happened and the next step. A caller whose plan renews hears when, as in "Your credits renew on Oct 10, 2026. Top up to keep reading." A caller whose plan payment failed hears to update the payment or top up. example: Insufficient credits. Top up or subscribe to continue. next_step: type: string description: What to do next. A key that reads only gets the account page, since it cannot open checkout. enum: - Ask the user to confirm a payment option before creating checkout. - Ask the user to top up at /dashboard/account. This key cannot open checkout. payment_options: type: object description: Checkout actions. Absent for a key that reads only. additionalProperties: false required: [credits] properties: credits: type: object additionalProperties: false required: [create_checkout] properties: create_checkout: type: object additionalProperties: false required: &checkout-action-required-fields - body - creates - method - path - provider - requires_authentication - requires_user_confirmation - response_url_field properties: body: type: object additionalProperties: false required: [dollars, locale] properties: dollars: type: integer const: 10 locale: type: string const: en creates: *checkout-url-field method: *post-method path: type: string const: /api/v1/credits/topup provider: *legacy-checkout-provider requires_authentication: *boolean-true requires_user_confirmation: *boolean-true response_url_field: type: string const: url subscription: type: object additionalProperties: false description: Absent for a caller on an active plan. required: [create_checkout] properties: create_checkout: type: object additionalProperties: false required: *checkout-action-required-fields properties: body: type: object additionalProperties: false required: [tier] properties: tier: type: string const: starter creates: *checkout-url-field method: *post-method path: type: string const: /api/v1/subscribe provider: *legacy-checkout-provider requires_authentication: *boolean-true requires_user_confirmation: *boolean-true response_url_field: type: string const: url required: type: string pattern: '^\d+$' description: Credits required for the blocked request. example: '1' top_up_endpoint: type: string const: /api/v1/credits/topup top_up_url: type: string const: POST /api/v1/credits/topup MppPaymentRequired: description: Anonymous payment requirement for a direct MPP operation. The response includes an MPP challenge and an accountless checkout action. type: object required: - account_required - detail - next_step - payment_options - status - title - type properties: account_required: *boolean-false challengeId: type: string description: Opaque identifier for the MPP payment challenge. example: mpp_challenge_example detail: type: string example: Payment is required. hint: type: string description: Instructions for selecting and paying an MPP offer. example: Use a supported wallet with an offer from the WWW-Authenticate header. next_step: type: string const: Ask the user to confirm a USD amount before creating checkout. payment_options: *guest-payment-options status: type: integer const: 402 title: type: string const: Payment Required type: type: string format: uri const: https://paymentauth.org/problems/payment-required Error: description: > Error response. Default v1 returns a legacy string code. Send `xquik-api-contract: 2026-04-29` for the structured best-practice error object. type: object required: [error] properties: error: x-stainless-naming: python: type_name: ErrorValue java: type_name: ErrorValue example: invalid_input oneOf: - type: string title: LegacyErrorCode enum: &public-error-codes - internal_error - account_already_connected - account_needs_reauth - account_not_found - account_required - account_restricted - api_key_limit_reached - article_not_found - closed - dm_not_permitted - invalid_format - invalid_id - invalid_input - invalid_media_url - invalid_message_id - invalid_params - invalid_tool_type - invalid_tweet_id - invalid_tweet_url - invalid_user_id - invalid_user_ids - invalid_username - invalid_json - insufficient_credits - job_not_found - login_cooldown - login_failed - media_download_failed - media_too_large - missing_params - missing_query - monitor_already_exists - monitor_profile_unavailable - no_media - no_credits - no_subscription - not_found - payment_failed - rate_limit_exceeded - service_unavailable - session_required - style_not_found - subscription_inactive - tweet_not_found - unauthenticated - unsupported_field - user_not_found - body_too_large - bookmark_folders_unavailable - broadcast_not_found - checkout_unavailable - connection_challenge_expired - connection_challenge_inactive - contributor_not_found - coverage_cursor_gone - coverage_cursor_unavailable - cursor_account_unavailable - draft_not_found - draw_too_large - expired - favoriters_unavailable - forbidden - guest_wallet_unavailable - guest_wallets_disabled - guest_wallets_unavailable - idempotency_conflict - idempotency_in_progress - idempotency_key_conflict - invalid_broadcast_id - invalid_community_id - invalid_community_topic - invalid_complete_replies_request - invalid_contributor_alias - invalid_coverage_cursor - invalid_coverage_request - invalid_cursor - invalid_idempotency_key - invalid_job_filter - invalid_job_id - invalid_list_id - invalid_news_id - invalid_output_options - invalid_payment_amount - invalid_range - invalid_reply_options - invalid_space_id - likes_unavailable - list_not_found - login_rate_limited - login_service_unavailable - missing_idempotency_key - missing_ids - missing_url - news_not_found - no_cached_style - pagination_stalled - passkey_required - rate_limited - read_request_timeout - replay_unavailable - replies_incomplete - retweeters_incomplete - search_unavailable - space_canceled - space_not_ended - support_media_rate_limit - support_request_rate_limit - telegram_unavailable - too_many_ids - too_many_streams - too_many_tweets - unknown_field - unsupported_media_combination - unsupported_media_type - webhook_inactive - write_tracking_unavailable - x_write_unconfirmed - x_account_feature_required - x_account_protected - x_account_suspended - x_api_rate_limited - x_api_unavailable - x_api_unauthorized - x_auth_failure - x_automation_refused - x_community_not_joined - x_community_not_selectable - x_community_post_public - x_community_post_removed - x_content_too_long - x_daily_limit - x_dm_not_allowed - x_dm_not_deleted - x_dm_not_sent - x_duplicate_action - x_login_auth_failed - x_login_challenge - x_login_denied - x_login_failed - x_login_rate_limited - x_login_service_unavailable - x_login_suspended - x_image_invalid - x_media_rejected - x_post_not_sent - x_rate_limited - x_rejected - x_reply_not_allowed - x_reply_target_unavailable - x_target_not_found - x_transient_error - x_user_lookup_failed - x_write_ambiguous - x_write_failed example: invalid_input - type: object title: StructuredError required: [message, type, code] properties: message: type: string example: 'Invalid input. Check the request body.' type: type: string enum: - api_error - authentication_error - billing_error - dependency_error - invalid_request_error - permission_error - rate_limit_error example: invalid_request_error code: type: string title: ErrorCode enum: *public-error-codes example: invalid_input message: type: string description: Human-readable error guidance. example: 'Invalid input. Check the request body.' reason: type: string description: > Machine-readable reason. A login failure names its cause, such as temporary_issue. A user_not_found answer names why X shows no profile, as not_found or suspended. A tweet_not_found answer names why X shows no post, when X said, as deleted, author_suspended or protected. example: temporary_issue retryAfter: type: integer minimum: 1 description: Seconds until the next permitted request. example: 60 retryAfterMs: type: integer minimum: 1 description: Required wait in milliseconds. example: 60000 allowedFields: type: array maxItems: 400 description: > With unknown_field, the valid names where the first unknown name in fields or omit stopped. example: ['author.id', 'author.username'] items: type: string example: author.username fieldErrors: type: array maxItems: 200 description: > With unknown_field, each unknown name in fields or omit, with the name it most likely meant. example: - code: unknown_field field: author.usrname message: Unknown field author.usrname. Did you mean author.username? path: query.fields suggestion: author.username items: type: object required: [code, field, message, path] properties: code: type: string const: unknown_field example: unknown_field field: type: string description: The name as the request wrote it. example: author.usrname message: type: string description: What to send instead. example: Unknown field author.usrname. Did you mean author.username? path: type: string enum: [query.fields, query.omit] description: The parameter that held the name. example: query.fields suggestion: type: string description: The closest valid name, when 1 is close. example: author.username EventType: description: > Type of monitor event fired when account activity occurs. tweet.deleted fires once X confirms the account deleted a post the monitor saw. Its data is the post as last seen. broadcast.started & space.started fire when the account posts its running live video or Space. Their data is that post. Xquik misses a live video the account does not post. following.added & following.removed fire when the account follows or unfollows someone, with that account's profile. follower.added & follower.removed fire when someone follows the account or leaves its followers, with that account's profile. Xquik names lost followers for accounts with up to 100,000 followers. profile.followers.changed & profile.following.changed fire when the account's follower or following count moves, at most once a minute each. X shows counts that differ by a few between reads, so a monitor holds the lowest. A fall counts once 2 reads show it, & a rise once no read for a minute showed less. Keyword monitors take the 10 post types only. type: string enum: - tweet.new - tweet.reply - tweet.retweet - tweet.quote - tweet.media - tweet.link - tweet.poll - tweet.mention - tweet.hashtag - tweet.longform - profile.avatar.changed - profile.banner.changed - profile.name.changed - profile.username.changed - profile.bio.changed - profile.location.changed - profile.url.changed - profile.verified.changed - profile.protected.changed - profile.pinned_tweet.changed - profile.unavailable.changed - tweet.deleted - broadcast.started - space.started - following.added - following.removed - follower.added - follower.removed - profile.followers.changed - profile.following.changed example: 'tweet.new' EventTypeArray: description: Array of event types to subscribe to. type: array items: $ref: '#/components/schemas/EventType' minItems: 1 maxItems: 30 example: ['tweet.new', 'tweet.reply'] ExtractionToolType: description: Identifier for the extraction tool used to run a job. type: string example: 'follower_explorer' enum: - article_extractor - community_extractor - community_moderator_explorer - community_post_extractor - community_search - favoriters - follower_explorer - following_explorer - list_follower_explorer - list_member_extractor - list_post_extractor - mention_extractor - people_search - post_extractor - quote_extractor - reply_extractor - repost_extractor - space_explorer - thread_extractor - tweet_search_extractor - user_likes - user_media - verified_follower_explorer ExtractionRequest: description: 1 estimate or extraction. Leave out filters you do not need. type: object example: { toolType: follower_explorer, targetUsername: elonmusk } required: [toolType] properties: toolType: type: string $ref: '#/components/schemas/ExtractionToolType' targetTweetId: type: string maxLength: 19 targetUsername: type: string maxLength: 19 targetCommunityId: type: string maxLength: 19 description: Required for community_post_extractor & community_search. targetListId: type: string maxLength: 19 description: Required for list_follower_explorer, list_member_extractor & list_post_extractor. targetSpaceId: type: string maxLength: 13 description: Required for space_explorer. X names a Space's hosts & speakers without counts or bio, so Xquik reads each one's profile. Rows carry it, & profile filters such as minFollowers check it. targetTweetIds: type: array minItems: 1 maxItems: 10000 uniqueItems: true items: type: string maxLength: 19 description: Tweet IDs processed as 1 collection job. targetUsernames: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string maxLength: 19 description: Usernames processed concurrently in 1 job. With tweet_search_extractor, each username collects posts. Post & media jobs skip a protected profile & end with partial_failure. targetCommunityIds: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string maxLength: 19 description: Community IDs processed as 1 collection job. targetListIds: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string maxLength: 19 description: List IDs processed as 1 collection job. searchQueries: type: array minItems: 1 maxItems: 100 uniqueItems: true items: type: string maxLength: 4096 description: Search queries processed as 1 collection job. Each follows the rules of searchQuery, its structured fields & 512-character limit included. targets: type: array maxItems: 10000 items: $ref: '#/components/schemas/ExtractionMixedTarget' description: > Mixed targets auto-routed within 1 job. Use tweet, replies, quotes, thread, or profile_media kinds to collect attached media. The job skips protected profiles & ends with partial_failure. relationTargets: type: array maxItems: 100 items: $ref: '#/components/schemas/ExtractionRelationTarget' description: Profile relations processed within 1 job. The job skips protected profiles & ends with partial_failure. queryType: type: string enum: [Latest, Top, Both, relevance] default: Latest description: Use Top for engagement. The relevance alias maps to Top. maxItemsPerTarget: type: integer minimum: 1 description: Maximum results collected for each target. maxPagesPerTarget: type: integer minimum: 1 maximum: 1000 description: Reply pages collected for each target. startCursor: type: string maxLength: 4096 minLength: 1 description: Resume 1 reply target from this cursor. dedupeAcrossTargets: type: boolean default: true description: Merge duplicate results across collection targets. dedupeMode: type: string enum: [none, first, merge] description: Keep target duplicates, first rows, or merged overlap. overlapMode: type: boolean default: false description: Shortcut for dedupeMode=merge. includeSearchTerms: type: boolean default: false description: Add matching search terms to collection metadata. includeTargetMetadata: type: boolean default: true description: Add source target metadata to each result. enrichProfiles: type: boolean default: false description: > Add each user's full profile to follower_explorer, following_explorer, verified_follower_explorer, people_search & repost_extractor rows. Jobs take longer. collectionStrategy: type: string enum: [auto, complete, direct, search, thread] default: auto description: Reply collection strategy. scope: type: string enum: [all, direct, nested] default: all description: Reply depth scope. maxDepth: type: integer minimum: 1 description: Maximum nested reply depth. sort: type: string enum: [relevance, latest, oldest, likes] default: relevance description: Reply result order. excludeOriginalAuthor: type: boolean default: false description: Exclude replies from the source author. includeOriginalPost: type: boolean default: false description: Include the source post in reply results. hasMediaOnly: type: boolean default: false description: Return only replies with media. sinceTime: oneOf: - type: string format: date-time maxLength: 64 - $ref: '#/components/schemas/WholeNumber' description: Reply start time as ISO 8601 or Unix seconds. untilTime: oneOf: - type: string format: date-time maxLength: 64 - $ref: '#/components/schemas/WholeNumber' description: Reply end time as ISO 8601 or Unix seconds. minViews: type: integer minimum: 0 description: Tweet or Community search minimum views. minBookmarks: type: integer minimum: 0 description: Minimum Tweet bookmark count. maxLikes: type: integer minimum: 0 description: Maximum Tweet like count. maxRetweets: type: integer minimum: 0 description: Maximum Tweet repost count. maxReplies: type: integer minimum: 0 description: Maximum Tweet reply count. maxQuotes: type: integer minimum: 0 description: Maximum Tweet quote count. blueVerifiedOnly: type: boolean default: false description: Return only Blue-verified Tweet authors. On a tool that returns users, return only profiles X marks as blue verified. cardName: type: string maxLength: 512 description: Require Tweet cards whose name matches this value. source: type: string maxLength: 512 deprecated: true description: X search no longer supports source. An extraction with it answers 424 `search_unavailable` & charges nothing. excludeSource: type: string maxLength: 512 deprecated: true description: X search ignores excludeSource, so an extraction with it returns unfiltered rows. Its answers carry `Deprecation` & `Sunset` headers. From 2027-01-15 an extraction with it answers 424 `search_unavailable` & charges nothing. geocode: type: string maxLength: 512 deprecated: true description: X search no longer supports geocode. An extraction with it answers 424 `search_unavailable` & charges nothing. sinceId: type: string maxLength: 19 description: Require Tweet IDs above this ID. maxId: type: string maxLength: 19 description: Require Tweet IDs at or below this ID. near: type: string maxLength: 512 description: > Restrict Tweet search to this place name. A country, such as Brazil, works like placeCountry. A city keeps Tweets about it. within: type: string maxLength: 512 deprecated: true description: X search no longer supports within. An extraction with it answers 424 `search_unavailable` & charges nothing. Use near alone. withinTime: type: string maxLength: 64 description: Restrict Tweets to this recent time window. nativeRetweets: type: boolean default: false description: Tweet or Community search native reposts. safe: type: boolean default: false description: Apply safe-search filtering to Tweet results. news: type: boolean default: false deprecated: true description: X search no longer supports filter:news. An extraction with news true answers 424 `search_unavailable` & charges nothing. minFollowers: type: integer minimum: 0 description: Minimum follower count for profile results. maxFollowers: type: integer minimum: 0 description: Maximum follower count for profile results. minFollowing: type: integer minimum: 0 description: Minimum following count for profile results. maxFollowing: type: integer minimum: 0 description: Maximum following count for profile results. minPosts: type: integer minimum: 0 description: Minimum post count for profile results. maxPosts: type: integer minimum: 0 description: Maximum post count for profile results. minAccountAgeDays: type: integer minimum: 0 description: Minimum profile age in days. verifiedType: type: string maxLength: 100 description: Exact profile verification type. hasWebsite: type: boolean default: false description: Require a profile website. hasLocation: type: boolean default: false description: Require a profile location. hasEmail: type: boolean default: false description: Require an email the profile publishes. businessEmailOnly: type: boolean default: false description: Require an email the profile publishes outside free webmail, such as Gmail. emailDomains: type: string maxLength: 4096 description: Require an email at one of these domains. Separate domains with commas. Subdomains match. example: acme.com,stanford.edu bioContains: type: string maxLength: 4096 description: Match any bio term, ignoring case. Separate terms with commas or lines. locationContains: type: string maxLength: 100 description: Required profile location text. usernameContains: type: string maxLength: 100 description: Required username text. resultsLimit: type: integer minimum: 1 default: 10000 description: > Maximum unique results to emit. Xquik bills emitted results, not this upper bound. searchQuery: type: string maxLength: 4096 description: Required for tweet_search_extractor, people_search & community_search. tweet_search_extractor adds the structured search fields, such as fromUser & minFaves, to this query. X searches up to 512 characters. A longer tweet or people search answers 400, counted with the added fields. fromUser: type: string maxLength: 19 description: Filter by author username (tweet_search_extractor) toUser: type: string maxLength: 19 description: Replies to this username (tweet_search_extractor). mentioning: type: string maxLength: 19 description: Mentions this username (tweet_search_extractor). language: type: string maxLength: 35 description: Tweet or Community search language. sinceDate: type: string format: date maxLength: 64 description: Tweet or Community search start date. untilDate: type: string format: date maxLength: 64 description: Tweet or Community search end date. mediaType: type: string enum: [images, videos, gifs, media, links, none] description: Tweet or Community search media. minFaves: type: integer minimum: 0 description: Tweet or Community search minimum likes. minRetweets: type: integer minimum: 0 description: Tweet or Community search minimum reposts. minReplies: type: integer minimum: 0 description: Tweet or Community search minimum replies. minQuotes: type: integer minimum: 0 description: Minimum quote count threshold (tweet_search_extractor) verifiedOnly: type: boolean description: Tweet or Community search verified authors. replies: type: string enum: [include, exclude, only] description: Choose whether tweet search includes, excludes, or isolates replies. retweets: type: string enum: [include, exclude, only] description: Choose whether tweet search includes, excludes, or isolates reposts. quotes: type: string enum: [include, exclude, only] description: Choose whether tweet search includes, excludes, or isolates quotes. exactPhrase: type: string maxLength: 4096 description: Exact phrase to match (tweet_search_extractor) excludeWords: type: string maxLength: 4096 description: Excluded terms or phrases (tweet_search_extractor). anyWords: type: string maxLength: 4096 description: Any matching term or phrase (tweet_search_extractor). hashtags: type: string maxLength: 4096 description: Matching hashtags (tweet_search_extractor). cashtags: type: string maxLength: 4096 description: Matching cashtags (tweet_search_extractor). url: type: string maxLength: 2048 description: URL substring or domain filter (tweet_search_extractor) conversationId: type: string maxLength: 19 description: Conversation ID filter (tweet_search_extractor) inReplyToTweetId: type: string maxLength: 19 description: Only replies to this tweet ID (tweet_search_extractor) quotesOfTweetId: type: string maxLength: 19 description: Only quotes of this tweet ID (tweet_search_extractor) retweetsOfTweetId: type: string maxLength: 19 description: Only retweets of this tweet ID (tweet_search_extractor) listId: type: string maxLength: 19 description: Search within a list ID (tweet_search_extractor) place: type: string maxLength: 512 description: Search within a place ID (tweet_search_extractor) placeCountry: type: string maxLength: 512 description: Search within a country code (tweet_search_extractor) pointRadius: type: string maxLength: 512 description: Geo point radius, such as -73.99 40.73 25mi (tweet_search_extractor) boundingBox: type: string maxLength: 512 description: Geo bounding box, such as -74.1 40.6 -73.9 40.8 (tweet_search_extractor) advancedQuery: type: string maxLength: 4096 description: Raw advanced search query appended as-is (tweet_search_extractor) ExtractionEstimate: description: Free conservative cost estimate. Post estimates use the supported cap & refuse a protected profile. It never creates a job or charges. type: object required: [allowed, creditsAvailable, creditsRequired, estimatedResults, source] properties: allowed: type: boolean description: Whether the balance covers the full estimate. example: true creditsAvailable: type: string example: '50000' creditsRequired: type: string example: '500' estimatedResults: type: integer minimum: 0 description: The row count the credit estimate uses. It does not say how many rows exist. example: 500 resolvedXUserId: type: string description: Resolved X user ID from count-based profile estimates. example: '123456' source: type: string enum: [ followers, following, collection, likeCount, paginationCap, quoteCount, replyCount, resultsLimit, retweetCount, unknown, ] example: replyCount ExtractionMixedTarget: description: 1 auto-routed target in a mixed Tweet collection. oneOf: - type: string maxLength: 4096 description: > X URL, numeric Tweet ID, @username, kind:value target, or search. - type: object required: [kind, value] properties: kind: type: string enum: - favoriters - list - profile - profile_likes - profile_media - profile_replies - quotes - replies - retweeters - search - thread - tweet value: type: string maxLength: 4096 minLength: 1 ExtractionRelationTarget: description: 1 target and relation in a mixed profile collection. type: object required: [relation, value] properties: relation: type: string enum: - community_members - followers - following - list_followers - list_members - verified_followers value: type: string maxLength: 19 minLength: 1 ApiKey: description: API key metadata returned when listing keys. type: object required: [id, name, prefix, isActive, createdAt] properties: id: type: string name: type: string prefix: type: string isActive: type: boolean createdAt: *date-time-string lastUsedAt: *date-time-string Monitor: description: Account monitor that tracks activity for a given X user. type: object required: [id, username, xUserId, eventTypes, isActive, createdAt, nextBillingAt] properties: id: *resource-id-example-schema username: *username-example-schema xUserId: *user-id-example-schema name: type: string description: Customer-set label of the account monitor, when set. example: Launch watch eventTypes: *event-types isActive: *boolean-example-true createdAt: *created-at-schema nextBillingAt: type: string format: date-time description: Next hourly credit charge time for this account monitor. example: '2025-01-15T12:00:00Z' pausedReason: type: string enum: [insufficient_credits, x_account_protected, x_user_not_found] description: Why Xquik paused this account monitor. `insufficient_credits` means the balance could not pay an hour, so add credits & resume. The other 2 mean X stopped showing the account. Absent when the monitor is active or you paused it yourself. example: x_user_not_found pausedAt: type: string format: date-time description: When Xquik paused this account monitor. example: '2025-01-15T12:00:00Z' KeywordMonitor: description: Keyword monitor that tracks matching public X activity. type: object required: [id, query, eventTypes, isActive, createdAt, nextBillingAt] properties: id: type: string example: '21' query: type: string example: 'xquik OR "x api"' name: type: string description: Customer-set label of the keyword monitor, when set. example: Launch mentions eventTypes: *single-event-type isActive: *boolean-example-true createdAt: *created-at-schema nextBillingAt: type: string format: date-time description: Next hourly credit charge time for this keyword query monitor. example: '2025-01-15T12:00:00Z' pausedReason: type: string enum: [insufficient_credits] description: Why Xquik paused this keyword monitor. The balance could not pay an hour, so add credits & resume. Absent when the monitor is active or you paused it yourself. example: insufficient_credits pausedAt: type: string format: date-time description: When Xquik paused this keyword monitor. example: '2025-01-15T12:00:00Z' Event: description: Monitor event summary with source metadata and occurrence time. type: object required: [id, type, monitorId, monitorType, occurredAt, data] properties: id: type: string type: $ref: '#/components/schemas/EventType' username: type: string description: Current account username, present for account monitor events. xUserId: type: string description: Permanent X user ID of the monitored account, present for account monitor events. It stays the same after a username change. query: type: string description: Keyword query, present for keyword monitor events. monitorId: type: string description: Account monitor ID for account events, or keyword monitor ID for keyword events. monitorName: type: string description: Your monitor label when Xquik created the event, present when set. A rename leaves the event's label unchanged. monitorType: type: string enum: [account, keyword] description: Source monitor type. keywordMonitorId: type: string description: Keyword monitor ID, present for keyword monitor events. occurredAt: type: string format: date-time description: X's time of the event when X gives one, as for a post, a live video & a Space. Otherwise, the time Xquik saw it, as for a deleted post, a profile change & a follow list change. data: $ref: '#/components/schemas/MonitorEventData' EventDetail: description: Full monitor event including payload data and optional X event ID. type: object required: [id, type, monitorId, monitorType, occurredAt, data] properties: id: *resource-id-example-schema type: type: string $ref: '#/components/schemas/EventType' example: 'tweet.new' username: type: string description: Current account username for this detailed event. example: 'elonmusk' xUserId: type: string description: Permanent X user ID of the monitored account on account events. It stays the same after a username change. example: '44196397' query: type: string description: Keyword query for this detailed monitor event. example: 'xquik OR "x api"' monitorId: type: string description: Monitor ID associated with this detailed event payload. example: '10' monitorName: type: string description: Your monitor label when Xquik created this event, present when set. A rename leaves the event's label unchanged. example: Launch watch monitorType: type: string enum: [account, keyword] description: Source monitor type for this detailed event. example: account keywordMonitorId: type: string description: Keyword monitor ID included on detailed keyword events. example: '21' occurredAt: type: string format: date-time description: When the event happened by X's clock, for a post, a live video or a Space. X gives no time for a deleted post, a profile change or a follow list change, so those hold when Xquik saw them. example: '2025-01-15T12:00:00Z' data: type: object $ref: '#/components/schemas/MonitorEventData' description: Post or profile-change payload for the event type. example: id: '1234567890' text: The future is now. author: id: '44196397' username: elonmusk userName: elonmusk verified: true rawVerified: false xEventId: *tweet-id-example-schema MonitorEventData: description: Post fields match REST. Legacy fields remain available. anyOf: - $ref: '#/components/schemas/MonitorPost' - $ref: '#/components/schemas/MonitorProfileChange' - $ref: '#/components/schemas/MonitorFollow' - $ref: '#/components/schemas/MonitorLegacyPost' MonitorFollow: description: The other account of a following or follower event, with the profile fields a user lookup returns. It holds the ID alone when X fails the profile lookup. type: object required: [id] properties: id: type: string description: The other account's X user ID. example: '2244994945' followedAt: type: string format: date-time description: X's time of the follow, on following.added & follower.added. It is missing when X gives none, as for an account that returns to a list. example: '2026-10-13T02:36:54.961Z' followedAtExact: type: boolean description: Whether followedAt is X's exact time of this follow. When several accounts join between 2 checks, X times the first, the second & the last. Each other one holds the earliest time its follow can have, with false here. example: true reason: type: string enum: [unavailable, unfollowed] description: Why the account left the list, on following.removed & follower.removed. unavailable means X no longer serves the account. unfollowed means X's follow check says the follow ended. It is missing when X fails the check. Xquik sends no removal while X still confirms the follow. example: unfollowed additionalProperties: true MonitorLegacyPost: description: Older stored posts remain readable. Fields can be missing or null. type: object properties: id: type: string text: type: string author: type: [object, 'null'] additionalProperties: true quoted_tweet: type: [object, 'null'] additionalProperties: true retweeted_tweet: type: [object, 'null'] additionalProperties: true additionalProperties: true MonitorPost: description: Monitored post with public fields and retained legacy fields. allOf: - $ref: '#/components/schemas/TweetPublicData' - type: object properties: author: type: object $ref: '#/components/schemas/MonitorProfile' card: type: object allOf: - $ref: '#/components/schemas/TweetCard' - type: object properties: userReferences: type: array items: type: object $ref: '#/components/schemas/MonitorProfile' reactionContext: type: object properties: reactedToPostId: type: string reactedToUser: type: object $ref: '#/components/schemas/MonitorProfile' quoted_tweet: type: object $ref: '#/components/schemas/MonitorEmbeddedPost' retweeted_tweet: type: object $ref: '#/components/schemas/MonitorEmbeddedPost' additionalProperties: true MonitorEmbeddedPost: description: Embedded post with public fields and legacy profile aliases. allOf: - $ref: '#/components/schemas/EmbeddedTweet' - type: object properties: author: type: object $ref: '#/components/schemas/MonitorProfile' MonitorProfile: description: Public profile with retained legacy monitor fields. allOf: - $ref: '#/components/schemas/UserProfile' - type: object properties: userName: type: string deprecated: true description: Legacy username alias. Read username instead. rawVerified: type: boolean deprecated: true description: Original X flag. Read verified for the displayed badge. additionalProperties: true MonitorProfileChange: description: Changed profile field with its previous and current values. The field of a count event is followers or following, with both counts as integers. type: object required: [field, userId, username] properties: field: type: string change: type: integer format: int64 minimum: -9007199254740991 maximum: 9007199254740991 description: Current count minus previous count. Only on the 2 count events. example: -3 userId: type: string description: Permanent X user ID. username: type: string description: Username observed for this change. previous: $ref: '#/components/schemas/MonitorProfileValue' current: $ref: '#/components/schemas/MonitorProfileValue' MonitorProfileValue: description: Profile text, flag, count, or pinned post IDs. Missing values are omitted. anyOf: - type: string - type: boolean - type: integer format: int64 minimum: 0 maximum: 9007199254740991 - type: array items: type: string ExtractionJob: description: Extraction job tracking status, tool type, and result count. type: object example: id: id toolType: follower_explorer status: completed totalResults: 0 createdAt: '2026-08-23T10:00:00Z' required: [id, toolType, status, totalResults, createdAt] properties: id: type: string toolType: $ref: '#/components/schemas/ExtractionToolType' status: type: string enum: [pending, running, canceled, completed, failed] totalResults: $ref: '#/components/schemas/WholeNumber' resultsLimit: type: integer minimum: 1 description: Requested result limit. effectiveResultsLimit: type: integer minimum: 0 description: Result limit after affordability checks. completionReason: type: string enum: [ budget_limited, canceled, deadline_reached, failed, pagination_safety_limit, partial_failure, requested_limit_reached, source_exhausted, ] description: Why a terminal job stopped. errorMessage: type: string description: Safe error code for a failed job. createdAt: { type: string, format: date-time } completedAt: { type: string, format: date-time } ExtractionResult: description: A public row from any supported extraction mode. type: object required: [id, xUserId, createdAt] additionalProperties: true properties: id: { type: string } xUserId: { type: string } xUsername: { type: string } xDisplayName: { type: string } xFollowersCount: type: integer minimum: 0 description: Followers of the account. Absent when X sends no count, as for the hosts & speakers of a Space, and never 0 in its place. xVerified: { type: boolean } xProfileImageUrl: { type: string, format: uri } email: type: string description: > First email the account publishes on its profile, with outputPreset=flat. Default nested output uses enrichmentData.user.email, beside enrichmentData.user.contactInfo. Absent when the profile publishes none. example: press@example.com tweetId: { type: string } tweetUrl: *uri-string tweetText: { type: string } tweetCreatedAt: { type: string, format: date-time } createdAt: { type: string, format: date-time } media: type: array description: > Attached media with outputPreset=flat. Default nested output uses enrichmentData.tweet.media. items: { $ref: '#/components/schemas/TweetMedia' } bookmarkCount: *whole-number likeCount: *whole-number quoteCount: *whole-number replyCount: *whole-number retweetCount: *whole-number viewCount: *whole-number enrichmentData: { $ref: '#/components/schemas/PublicMetadata' } DrawListItem: description: Giveaway draw summary with entry counts and status. type: object required: [id, tweetUrl, status, totalEntries, validEntries, createdAt] properties: id: type: string description: Draw public ID for detail responses. example: 'f4bd00a2-7b4e-4e59-8e1b-72e2c9f12345' tweetUrl: *uri-string status: type: string totalEntries: $ref: '#/components/schemas/WholeNumber' validEntries: $ref: '#/components/schemas/WholeNumber' createdAt: *date-time-string drawnAt: *date-time-string DrawDetail: description: Full giveaway draw with tweet metrics, entries, and timing. example: *draw-detail-example allOf: - $ref: '#/components/schemas/DrawListItem' - type: object required: - tweetId - tweetText - tweetAuthorUsername - tweetLikeCount - tweetRetweetCount - tweetReplyCount - tweetQuoteCount properties: tweetId: type: string tweetText: type: string tweetAuthorUsername: type: string tweetLikeCount: $ref: '#/components/schemas/WholeNumber' tweetRetweetCount: $ref: '#/components/schemas/WholeNumber' tweetReplyCount: $ref: '#/components/schemas/WholeNumber' tweetQuoteCount: $ref: '#/components/schemas/WholeNumber' Winner: description: Giveaway draw winner with position and backup flag. type: object required: [authorUsername, tweetId, position, isBackup] properties: authorUsername: type: string tweetId: type: string position: type: integer minimum: 1 isBackup: type: boolean Webhook: description: Webhook endpoint registered to receive event deliveries. type: object required: - id - url - eventTypes - isActive - consecutiveFailures - deliveryStatus - failureHardCap - createdAt properties: id: *resource-id-example-schema url: type: string format: uri example: 'https://example.com/webhooks/xquik' eventTypes: *event-types isActive: *boolean-example-true consecutiveFailures: type: integer minimum: 0 description: Consecutive failed delivery attempts since the last success. example: 0 deliveryStatus: type: string enum: [active, paused, needs_attention] description: Endpoint delivery state. paused means the user paused delivery. needs_attention marks repeated failures. Delivery attempts continue. example: active failureHardCap: type: integer minimum: 1 description: Maximum reported failures before needs_attention. It does not pause delivery. example: 200 createdAt: *created-at-schema Delivery: description: Webhook delivery attempt record with status and retry count. type: object required: [id, streamEventId, status, attempts, createdAt] properties: id: type: string streamEventId: type: string status: type: string attempts: $ref: '#/components/schemas/WholeNumber' createdAt: *date-time-string deliveredAt: *date-time-string lastStatusCode: type: integer minimum: 0 maximum: 599 lastError: type: string ArticleAuthor: description: Available X Article author fields. type: object required: [id, name, username] properties: id: *user-id-example-schema name: type: string example: 'Elon Musk' username: *handle-example-schema description: type: string location: type: string url: type: string createdAt: type: string followersCount: $ref: '#/components/schemas/WholeNumber' followingCount: $ref: '#/components/schemas/WholeNumber' statusesCount: $ref: '#/components/schemas/WholeNumber' mediaCount: $ref: '#/components/schemas/WholeNumber' favouritesCount: $ref: '#/components/schemas/WholeNumber' profilePicture: type: string profilePictureOriginal: type: string description: The same profile picture at full size. profileBannerUrl: type: string isBlueVerified: type: boolean isVerified: type: boolean isTranslator: type: boolean protected: type: boolean JobAccount: description: > The X account that posted a job. A job has none when X imported it from a job board or no longer shows the account. type: object required: [id, verified] properties: id: type: string description: X user ID of the account. example: '1812126202804711425' username: type: string description: Handle without @. example: 'commonwarexyz' name: type: string description: Display name of the account that posted the job. example: 'commonware' verified: type: boolean description: Whether X shows a verification badge on the account. example: true verifiedType: type: string description: Badge type, such as Business or Government. example: 'Business' description: type: string description: Bio of the account. A job lookup returns it. profilePicture: type: string description: Avatar URL of the account that posted the job. profilePictureOriginal: type: string description: The job account's avatar at full size. profileImageShape: type: string description: Avatar shape, such as Circle or Square. example: 'Square' JobCompany: description: The company profile of a job X imported from a job board. type: object required: [id] properties: id: type: string description: X company profile ID. example: '1714017006498824192' name: type: string description: Company name. example: 'TotalMed' logoUrl: type: string description: Company logo URL. Job: description: > Public X job listing. A search returns the fields down to the salary, plus company & account. A lookup adds work type, seniority, function, team & descriptions. A field X leaves empty is left out. type: object example: id: '1899202395210649861' title: 'Engineer' url: 'https://x.com/i/jobs/1899202395210649861' applyUrl: 'https://commonware.xyz/hiring.html?utm_source=la37oZNq55&ashby_jid=d34716f5-0515-42f8-849a-c8fbac36c488' location: 'United States' locationType: 'remote' employmentType: 'full_time' seniorityLevel: 'lead' jobFunction: 'software_engineering' formattedSalary: 'Starting at $225K' salaryMin: 225000 salaryCurrencyCode: 'USD' salaryInterval: 'annually' featured: true shortDescription: 'Commonware is hiring for founding engineers that can help us expand the Commonware Library to a broader set of applications and deploy cloud-based components to augment it.' description: "What is Commonware?\n\nToday's blockchain stack is designed to be a jack of all trades, but master of none. Modeled after virtual machines (VM) and kernels, it exposes a monolithic interface through a one-size-fits-all framework instead of molding to the needs of any specific application.\nAt Commonware, we believe that the most popular onchain experiences of the next decade will develop a sustained edge through vertical integration. To accelerate developers that share this perspective, we are building a library of open (MIT/Apache-2) primitives meant to be remixed and modded.\nStreaming unstructured data over globally distributed infrastructure" descriptionMarkdown: "# What is Commonware?\n\nToday’s blockchain stack is designed to be a jack of all trades, but master of none. Modeled after virtual machines (VM) and kernels, it exposes a monolithic interface through a one-size-fits-all framework instead of molding to the needs of any specific application.\n\nAt Commonware, we believe that the most popular onchain experiences of the next decade will develop a sustained edge through vertical integration. To accelerate developers that share this perspective, we are building a [library of open (MIT/Apache-2) primitives](https://github.com/commonwarexyz/monorepo) meant to be remixed and modded.\n\n- Streaming unstructured data over globally distributed infrastructure" account: id: '1812126202804711425' username: 'commonwarexyz' name: 'commonware' verified: true verifiedType: 'Business' profilePicture: 'https://pbs.twimg.com/profile_images/1812494863784378368/1Iqip1ir_normal.jpg' profileImageShape: 'Square' required: [id, url] properties: id: type: string description: Job ID. example: '1899202395210649861' title: type: string description: Job title. example: 'Engineer' url: type: string description: The job page on X. example: 'https://x.com/i/jobs/1899202395210649861' applyUrl: type: string description: Where applicants apply, off X. example: 'https://xquik.com/example' location: type: string description: Location as the employer wrote it. example: 'United States' locationType: type: string description: Where the work happens (onsite, remote or hybrid). example: 'remote' employmentType: type: string description: > Contract type (full_time, full_time_contract, part_time or contract_to_hire). example: 'full_time' seniorityLevel: type: string description: > Seniority (intern, entry_level, junior, mid_level, senior, lead, manager or executive). example: 'lead' jobFunction: type: string description: Job function, such as software_engineering. example: 'software_engineering' team: type: string description: Team inside the company. example: 'Protocol' postedAt: type: string format: date-time description: When the employer posted the job. example: '2025-10-04T08:30:00.000Z' formattedSalary: type: string description: Salary as X shows it. example: 'Starting at $225K' salaryMin: type: number description: Lowest salary, in salaryCurrencyCode per salaryInterval. example: 225000 salaryMax: type: number description: Highest salary, in salaryCurrencyCode per salaryInterval. example: 300000 salaryCurrencyCode: type: string description: ISO 4217 currency code of the salary. example: 'USD' salaryInterval: type: string description: Pay period of the salary (annually or hourly). example: 'annually' featured: type: boolean description: Whether X features the job. shortDescription: type: string description: Short summary of the job, as plain text. description: type: string description: Full description as plain text, 1 line per paragraph. descriptionMarkdown: type: string description: > Full description as Markdown, with headings, lists, links, bold & italics. company: $ref: '#/components/schemas/JobCompany' account: $ref: '#/components/schemas/JobAccount' JobLocation: description: A place a job search can name by its ID. type: object required: [id, name] properties: id: type: string description: Location ID, which the job search locationId takes. example: '1720462281849397612' name: type: string description: Place name with its region or country code. example: 'New York, US' JobLocations: description: The places whose names match a query. type: object required: [locations, count] properties: locations: type: array description: Matching places, best match first. items: $ref: '#/components/schemas/JobLocation' example: - id: '1720462281849397612' name: 'New York, US' count: type: integer minimum: 0 description: Places returned, each charged 1 credit. example: 1 PaginatedJobs: description: > 1 page of job listings. Follow next_cursor while the response reports more pages. type: object example: { jobs: [], has_next_page: false, next_cursor: '' } required: [jobs, has_next_page, next_cursor] properties: jobs: type: array items: $ref: '#/components/schemas/Job' has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' CommunityNotesContributor: description: > A Community Notes contributor. X names contributors by an alias, never by their X account. A field X leaves out is left out. Beside a note, X sends its writer with only some of the counts. type: object required: [alias] example: *community-notes-contributor-example properties: alias: type: string description: The alias X gives the contributor. example: 'ardent-beach-friarbird' isTopWriter: type: boolean description: Whether X marks the contributor as a top writer. isApiContributor: type: boolean description: Whether the contributor writes notes through X's API. deletedNotesCount: type: integer $ref: '#/components/schemas/WholeNumber' description: Notes the contributor deleted. notesCount: $ref: '#/components/schemas/CommunityNotesNoteCounts' ratingsCount: $ref: '#/components/schemas/CommunityNotesRatingCounts' CommunityNotesNoteCounts: description: How many notes a contributor wrote, by X's current rating. type: object properties: awaitingMoreRatings: type: integer $ref: '#/components/schemas/WholeNumber' description: Notes that need more ratings. currentlyRatedHelpful: type: integer $ref: '#/components/schemas/WholeNumber' description: Notes X rates helpful now. currentlyRatedNotHelpful: type: integer $ref: '#/components/schemas/WholeNumber' description: Notes X rates not helpful now. updatedAt: type: string format: date-time description: When X last counted the notes. CommunityNotesRatingCounts: description: How a contributor's ratings of other notes went. type: object properties: awaitingMoreRatings: type: integer $ref: '#/components/schemas/WholeNumber' description: Ratings on notes that need more ratings. ratedAfterDecision: type: integer $ref: '#/components/schemas/WholeNumber' description: Ratings made after X rated the note. successful: type: object $ref: '#/components/schemas/CommunityNotesRatingOutcome' description: Ratings that matched the rating X gave the note. unsuccessful: type: object $ref: '#/components/schemas/CommunityNotesRatingOutcome' description: Ratings that went against the rating X gave the note. updatedAt: type: string format: date-time description: When X last counted the ratings. CommunityNotesRatingOutcome: description: A group of a contributor's ratings, by what each one said. type: object properties: helpfulCount: type: integer $ref: '#/components/schemas/WholeNumber' description: Ratings that called a note helpful. notHelpfulCount: type: integer $ref: '#/components/schemas/WholeNumber' description: Ratings that called a note not helpful. total: type: integer $ref: '#/components/schemas/WholeNumber' description: All ratings in the group, when X sends the sum. CommunityNote: description: > A Community Note as its writer's page lists it, with the post it is on. A deleted note has no text, classification or post. A field X leaves out is left out. type: object required: [id] properties: id: type: string description: Note ID. example: '2026375778254868976' createdAt: type: string format: date-time description: When the contributor wrote the note. language: type: string description: Language code of the note. example: 'en' classification: type: string description: What the writer says of the post, such as MisinformedOrPotentiallyMisleading or NotMisleading. example: 'MisinformedOrPotentiallyMisleading' text: type: string description: What the note says. contributor: type: object $ref: '#/components/schemas/CommunityNotesContributor' description: The note's writer, with the counts X sends beside a note. GET /x/community-notes/contributors/{alias} serves every count. entities: type: array description: Links, tags & accounts inside the text, by character range. items: $ref: '#/components/schemas/CommunityNoteEntity' ratingStatus: type: string description: X's current rating, such as NeedsMoreRatings, CurrentlyRatedHelpful or CurrentlyRatedNotHelpful. x.com shows only helpful notes under posts. example: 'CurrentlyRatedHelpful' helpfulTags: type: array items: { type: string } description: Why raters called the note helpful. example: ['ImportantContext', 'Clear'] notHelpfulTags: type: array items: { type: string } description: Why raters called the note not helpful. example: ['MissingKeyPoints', 'Incorrect'] decidedBy: type: string description: The X scoring model that set the rating. example: 'CoreModel (v1.1)' fullyVisibleModel: type: boolean description: Whether X marks that scoring model as fully visible. abovePcrhThreshold: type: boolean description: Whether the note scores above X's bar for a possible helpful rating. appealStatus: type: string description: Whether the rating is under appeal. example: 'NotAppealed' deleted: type: boolean description: Whether the writer deleted the note. tombstone: type: string description: X's notice in place of a deleted note. example: 'This note has been deleted' isApiAuthor: type: boolean description: Whether the note came through X's API. isMediaNote: type: boolean description: Whether the note is about the post's media. X can show such a note on other posts. mediaNoteMatchCount: type: integer $ref: '#/components/schemas/WholeNumber' description: Other posts X matched a media note to. isUrlNote: type: boolean description: Whether the note is on a link. displayUrl: type: string description: The link a link note is on, as X shows it. isTranslatable: type: boolean description: Whether X offers a translation of the note. timeToHelpfulFromNoteMs: type: integer $ref: '#/components/schemas/WholeNumber' description: Milliseconds from the note's creation to its helpful rating. example: 132890587 timeToHelpfulFromPostMs: type: integer $ref: '#/components/schemas/WholeNumber' description: Milliseconds from the post's creation to the note's helpful rating. example: 136815576 impressionCount: type: integer $ref: '#/components/schemas/WholeNumber' description: Views of the note, when X shares them. postId: type: string description: ID of the post the note is on. example: '2026359315657805939' post: anyOf: - $ref: '#/components/schemas/SearchTweet' - type: 'null' description: The post the note is on. Null when X no longer shows it. postUnavailable: type: object description: Why X shows no post, when X says. required: [reason] properties: reason: type: string description: Why X shows no post, as X names it. example: 'Suspended' CommunityNoteEntity: description: A link, tag or account inside a note's text. type: object properties: fromIndex: type: integer $ref: '#/components/schemas/WholeNumber' description: Where it starts in the text. toIndex: type: integer $ref: '#/components/schemas/WholeNumber' description: Where it ends in the text. ref: type: object description: What it points at. properties: type: type: string description: X's kind, such as TimelineUrl. example: 'TimelineUrl' url: type: string description: The link. example: 'https://t.co/7fJbcLrO1k' urlType: type: string description: How X opens the link, such as ExternalUrl. text: type: string description: A hashtag's or cashtag's text. screenName: type: string description: A mentioned account's username. PaginatedCommunityNotes: description: > 1 page of Community Notes. Follow next_cursor while the response reports more pages. type: object example: { notes: [], has_next_page: false, next_cursor: '' } required: [notes, has_next_page, next_cursor] properties: notes: type: array items: $ref: '#/components/schemas/CommunityNote' has_next_page: *boolean-example-true next_cursor: $ref: '#/components/schemas/NextCursor' TweetMedia: description: Tweet media. type: object required: [mediaUrl, type, url] properties: mediaUrl: { type: string, description: Preview URL. } type: { type: string, enum: [photo, video, animated_gif] } url: { type: string, description: Tweet media link. } adultContent: { type: boolean, description: Adult-content warning. } allowDownload: { type: boolean, description: Direct download permission. } altText: { type: string, description: Accessibility text. } aspectRatio: type: array description: Video width and height ratio. items: *whole-number availabilityReason: type: string description: Why X made the media unavailable, such as `Dmcaed` after a copyright report. Omitted on available media. example: Dmcaed availabilityStatus: type: string description: Availability state, such as `Available` or `Unavailable`. example: Available description: { type: string, description: Media description. } displayUrl: { type: string, description: Display URL. } durationMillis: type: integer minimum: 0 description: Video duration in milliseconds. expandedUrl: { type: string, description: Expanded media URL. } embeddable: { type: boolean, description: Embeddable status. } faceRects: type: object description: Face crop rectangles by size. additionalProperties: type: array items: &image-crop-schema type: object required: [x, 'y', w, h] properties: x: *whole-number 'y': *whole-number w: *whole-number h: *whole-number focusRects: type: array description: Suggested image crops. items: *image-crop-schema grokImageAnnotation: type: object description: > Prompt a Grok image came from. Absent on other media & when X sends no prompt. properties: prompt: type: string description: Prompt the image came from. upsampledPrompt: type: string description: Grok's longer rewrite of the prompt. grokPostId: { type: string, description: Grok post ID associated with the media. } graphicViolence: { type: boolean, description: Graphic-violence warning. } height: { type: integer, minimum: 0, description: Original height. } id: { type: string, description: Media entity ID. } indices: type: array description: Tweet text offsets. items: *whole-number mediaKey: { type: string, description: Stable X media key. } monetizable: { type: boolean, description: Monetization status. } otherSensitiveContent: { type: boolean } sizes: type: object description: Named media renditions and resize modes. additionalProperties: type: object required: [w, h, resize] properties: w: *whole-number h: *whole-number resize: { type: string } sourceStatusId: { type: string, description: Source tweet ID for copied media. } sourceUser: type: object $ref: '#/components/schemas/UserProfile' description: The account that first posted the media. Some reads carry only its name, picture & badges. sourceUserId: { type: string, description: Source profile ID for copied media. } tags: type: array description: Public profiles tagged in the media. items: type: object properties: name: { type: string } screen_name: { type: string } type: { type: string } user_id: { type: string } title: { type: string, description: Media title. } videoVariants: type: array description: Video encodings in source order. items: type: object required: [contentType, url] properties: bitrate: *whole-number contentType: { type: string } url: { type: string } watchNowUrl: { type: string, description: Public media action URL. } visitSiteUrl: { type: string, description: Public destination URL. } width: { type: integer, minimum: 0, description: Original width. } BookmarkFolder: description: Bookmark folder and its optional public cover image. type: object required: [id] properties: id: { type: string, description: Folder ID. } name: { type: string, description: Folder name. } media: type: object description: Public folder cover image metadata. properties: id: { type: string, description: Media object ID. } mediaId: { type: string, description: Media ID. } mediaKey: { type: string, description: Stable media key. } originalImageHeight: type: integer minimum: 0 description: Original image height. originalImageUrl: { type: string, description: Original image URL. } originalImageWidth: { type: integer, minimum: 0, description: Original image width. } palette: type: array description: Dominant image colors and their proportions. items: type: object properties: percentage: { type: number } rgb: type: object properties: blue: { type: number } green: { type: number } red: { type: number } type: { type: string, description: Media object type. } PublicMetadata: description: Public metadata whose fields X defines. type: object example: {} additionalProperties: true x-stainless-any: true x-stainless-terraform-type: string TweetArticleMetadata: description: An X Article preview and its lifecycle metadata. type: object properties: coverMedia: { $ref: '#/components/schemas/PublicMetadata' } id: { type: string } lifecycleState: { $ref: '#/components/schemas/PublicMetadata' } metadata: { $ref: '#/components/schemas/PublicMetadata' } title: { type: string } previewText: { type: string } coverMediaUrl: { type: string } TweetCard: description: A public card and the profiles it references. type: object properties: id: { type: string } name: { type: string } url: { type: string } bindingValues: { $ref: '#/components/schemas/PublicMetadata' } platform: $ref: '#/components/schemas/PublicMetadata' userReferenceErrors: description: Unresolved card user references. type: array items: type: object properties: message: type: string reason: type: string example: [{ message: User unavailable, reason: Suspended }] userReferences: { type: array, items: { $ref: '#/components/schemas/UserProfile' } } TweetCommunityNote: description: Community Note presentation metadata returned by X. type: object properties: id: { type: string } title: { type: string } shortTitle: { type: string } subtitle: { type: string } footer: { type: string } footerIconType: { type: string } destinationUrl: { type: string } iconType: { type: string } visualStyle: { type: string } metadata: { $ref: '#/components/schemas/PublicMetadata' } TweetAuthorUnavailable: description: Why the tweet has no author. X serves a suspended or deleted account as an unavailable user with a reason such as Suspended or NotFound. Omitted when the author is available. type: object required: [reason] properties: reason: { type: string, description: X's reason code., example: Suspended } message: { type: string, description: X's notice text for the reason. } TweetExclusiveContent: description: Marks a subscriber-only post with the creator whose subscription unlocks it. Non-subscribers get the preview text & the subscribe link. Omitted on public posts. type: object required: [creatorUserName] properties: creatorUserName: { type: string, description: Username of the creator whose subscription unlocks the post., } subscribeUrl: { type: string, description: Subscribe link X shows non-subscribers. Omitted when X serves the full post., } TweetSubscriberBadge: description: The Subscriber badge X shows on a reply. The reply's author subscribes to the creator who started the conversation. Omitted on a post without the badge. type: object required: [creatorId] properties: creatorId: type: string description: Account ID of the creator the author subscribes to. example: '44196397' TweetEdit: description: Lists edit-chain identifiers and the remaining edit window. type: object properties: editTweetIds: { type: array, items: { type: string } } editableUntilMsecs: { type: string } initialTweetId: { type: string } ResolvedLink: description: Pairs 1 t.co link with the URL it leads to. type: object required: [url] properties: url: type: string description: The t.co link, as `https://t.co/`. resolvedUrl: type: string description: Target URL, as the link's author set it. Xquik does not check it. Absent for a link t.co does not have. example: url: 'https://t.co/Xe1nm2pkSX' resolvedUrl: 'https://go.nasa.gov/3VcvAQn' TweetSubtitles: description: Holds the caption tracks of 1 tweet's videos. type: object required: [tweetId, tracks] properties: tweetId: type: string description: ID of the tweet. tracks: type: array description: Caption tracks, empty when no video has captions. items: $ref: '#/components/schemas/SubtitleTrack' example: tweetId: '2104593672624886205' tracks: - mediaKey: '13_2104593621043314689' language: en name: 'Planetary Defenders_Caption.en_US.srt' autoGenerated: false url: 'https://video.twimg.com/subtitles/amplify_video/2104593621043314689/0/-FdxBBY2iGcoP5wb.vtt' text: 'This asteroid 2024 YR4 might get interesting.' truncated: false cues: - startMs: 0 endMs: 3370 text: "This asteroid\n2024 YR4 might get interesting." SubtitleTrack: description: Holds 1 caption track of a video. type: object required: [autoGenerated, cues, text, truncated, url] properties: mediaKey: type: string description: Media key of the video, as media rows carry it. language: type: string description: Language code of the track, in lower case. name: type: string description: Track name the uploader or X gave it. autoGenerated: type: boolean description: True when X transcribed the audio itself. url: type: string description: Link to the track's first WebVTT file. text: type: string description: Every cue's text in order, as 1 line. truncated: type: boolean description: True when the track holds more than 50 caption files. The cues then cover the first 50. cues: type: array description: Timed captions in order. items: type: object required: [startMs, endMs, text] properties: startMs: type: integer minimum: 0 maximum: 86400000 description: Start time in milliseconds. endMs: type: integer minimum: 0 maximum: 86400000 description: End time in milliseconds. text: type: string description: Caption text, with a line break between lines. example: mediaKey: '13_2104593621043314689' language: en name: 'Planetary Defenders_Caption.en_US.srt' autoGenerated: false url: 'https://video.twimg.com/subtitles/amplify_video/2104593621043314689/0/-FdxBBY2iGcoP5wb.vtt' text: 'This asteroid 2024 YR4 might get interesting.' truncated: false cues: - startMs: 0 endMs: 3370 text: "This asteroid\n2024 YR4 might get interesting." TweetEmbed: description: Holds the HTML that embeds 1 tweet on a website. type: object required: [tweetId, url, authorName, authorUrl, html] properties: tweetId: type: string description: ID of the embedded tweet. url: type: string description: Link to the tweet with its author's username. authorName: type: string description: Display name of the tweet's author. authorUrl: type: string description: Link to the author's profile. html: type: string description: Markup to place on a page. It loads X's widget script unless `omitScript` is `true`. width: type: integer minimum: 1 maximum: 10000 description: Width of the embed in pixels. height: type: integer minimum: 1 maximum: 10000 description: Height in pixels, when X fixes it. example: tweetId: '2102882545427714266' url: 'https://x.com/NASA/status/2102882545427714266' authorName: NASA authorUrl: 'https://x.com/NASA' html: '' width: 550 TweetEntities: description: Lists hashtags, symbols, links, and mentions from tweet text. type: object properties: hashtags: { type: array, items: { $ref: '#/components/schemas/TweetHashtag' } } smarttags: { type: array, items: { $ref: '#/components/schemas/TweetSymbol' } } symbols: { type: array, items: { $ref: '#/components/schemas/TweetSymbol' } } timestamps: { type: array, items: { $ref: '#/components/schemas/TweetSymbol' } } urls: { type: array, items: { $ref: '#/components/schemas/TweetUrlEntity' }, } user_mentions: { type: array, items: { $ref: '#/components/schemas/TweetUserMention' }, } TweetHashtag: description: Hashtag text and its source offsets in a tweet. type: object required: [text] properties: indices: { type: array, items: *whole-number } tag: { $ref: '#/components/schemas/TweetSmartTag' } text: { type: string } TweetSymbol: description: Indexed smart-tag, cashtag, or video timestamp metadata. type: object properties: indices: { type: array, items: *whole-number } seconds: { type: number } text: { type: string } tag: { $ref: '#/components/schemas/TweetSmartTag' } TweetSmartTag: description: X's SmartTag for a cashtag, smarttag or hashtag. Xquik leaves out X's trading platforms, which differ by reader. type: object properties: id: type: string description: X's ID for the SmartTag. example: U21hcnRUYWc6VFNMQQ== info: type: object properties: info: type: object properties: active: type: boolean description: Whether X marks the SmartTag active. name: { type: string, example: Tesla Inc } ticker: { type: string, example: TSLA } TweetTranslation: description: Holds X's translation of 1 tweet into the requested language. `entities` holds the links, mentions, and tags with their offsets in the translated text, and is empty when the text has none. type: object required: [tweetId, language, text, entities] properties: tweetId: type: string description: ID of the translated tweet. example: '2102882545427714266' language: type: string description: Language code of the translated text, in lower case. example: tr sourceLanguage: type: string description: Language code X detects in the tweet, when it names one. example: en text: type: string description: Translated tweet text. example: 'Artemis Anlaşmaları’na Hoş Geldiniz, Hırvatistan https://t.co/Xe1nm2pkSX' entities: $ref: '#/components/schemas/TweetEntities' example: tweetId: '2102882545427714266' language: tr sourceLanguage: en text: 'Artemis Anlaşmaları’na Hoş Geldiniz, Hırvatistan https://t.co/Xe1nm2pkSX' entities: urls: - url: 'https://t.co/Xe1nm2pkSX' expanded_url: 'https://go.nasa.gov/3VcvAQn' display_url: go.nasa.gov/3VcvAQn indices: [49, 72] PostEngagementMetrics: description: The public counts of 1 tweet. type: object required: [likes, replies, reposts, quotes, bookmarks, views] properties: likes: type: number description: Likes. example: 9043 replies: type: number description: Replies. example: 207 reposts: type: number description: Reposts. example: 772 quotes: type: number description: Quotes. example: 100 bookmarks: type: number description: Bookmarks. example: 661 views: type: number description: Views. example: 1291231 UserInsights: description: > Engagement insights of 1 profile. Engagements are likes, replies, reposts and quotes. A rate is null when nothing divides it, such as a profile without posts of its own. type: object required: - userId - userName - followers - following - posts - accountAgeDays - postsPrivate - sample - averages - engagementRate - engagementPerView - postsPerDay - topPostId properties: userId: type: string description: ID of the profile the insights describe. example: '11348282' userName: type: string description: Username of that profile. example: NASA followers: type: number description: Followers. example: 92376187 following: type: number description: Accounts the user follows. example: 115 posts: type: number description: Posts the user has made. example: 74336 accountAgeDays: type: [number, 'null'] description: Whole days since the account joined X. example: 6858 postsPrivate: type: boolean description: >- True when only the account's followers see its posts. The report then has its counts only. example: false sample: type: object description: The recent posts the averages read. required: [posts, oldestAt, newestAt] properties: posts: type: number description: Posts read. example: 10 oldestAt: type: [string, 'null'] format: date-time description: When the oldest of them went up. example: '2026-09-23T13:15:28.000Z' newestAt: type: [string, 'null'] format: date-time description: When the newest of them went up. example: '2026-09-28T22:12:05.000Z' example: posts: 10 oldestAt: '2026-09-23T13:15:28.000Z' newestAt: '2026-09-28T22:12:05.000Z' averages: description: Each count per post of the sample. Null without posts. anyOf: - allOf: - $ref: '#/components/schemas/PostEngagementMetrics' - type: object required: [engagements] properties: engagements: type: number description: Likes, replies, reposts and quotes per post. example: 4331.7 - type: 'null' example: likes: 3684.2 replies: 142.7 reposts: 459.8 quotes: 45 bookmarks: 209.7 views: 785247.8 engagements: 4331.7 engagementRate: type: [number, 'null'] description: Average engagements per post, as a percent of followers. example: 0.0047 engagementPerView: type: [number, 'null'] description: Engagements as a percent of views across the sample. example: 0.5516 postsPerDay: type: [number, 'null'] description: Sampled posts per day, from the oldest one until now. example: 1.6814 topPostId: type: [string, 'null'] description: The sampled post with the most engagements. example: '2102761519985332442' example: *user-insights-example TweetInsights: description: > Engagement insights of 1 tweet. Engagements are likes, replies, reposts and quotes. A rate is null when nothing divides it, such as a tweet without views. type: object required: - tweetId - authorId - authorUserName - createdAt - ageHours - metrics - engagements - engagementsPerHour - engagementPerView - engagementRate - amplification - conversation properties: tweetId: type: string description: ID of the tweet the insights describe. example: '2102882545427714266' authorId: type: [string, 'null'] description: ID of the author. example: '11348282' authorUserName: type: [string, 'null'] description: Username of the author. example: NASA createdAt: type: [string, 'null'] format: date-time description: When the tweet went up. example: '2026-09-23T22:07:23.000Z' ageHours: type: [number, 'null'] description: Hours since the tweet went up. example: 133.88 metrics: $ref: '#/components/schemas/PostEngagementMetrics' engagements: type: number description: Likes, replies, reposts and quotes. example: 10122 engagementsPerHour: type: [number, 'null'] description: Engagements per hour since the tweet went up. example: 75.605 engagementPerView: type: [number, 'null'] description: Engagements as a percent of views. example: 0.7839 engagementRate: type: [number, 'null'] description: Engagements as a percent of the author's followers. example: 0.011 amplification: type: [number, 'null'] description: Reposts and quotes per like. example: 0.0964 conversation: type: [number, 'null'] description: Replies per like. example: 0.0229 example: tweetId: '2102882545427714266' authorId: '11348282' authorUserName: NASA createdAt: '2026-09-23T22:07:23.000Z' ageHours: 133.88 metrics: likes: 9043 replies: 207 reposts: 772 quotes: 100 bookmarks: 661 views: 1291231 engagements: 10122 engagementsPerHour: 75.605 engagementPerView: 0.7839 engagementRate: 0.011 amplification: 0.0964 conversation: 0.0229 UserLiveStatus: description: Says whether a user broadcasts live video on X now. `broadcast` is their latest broadcast, live or ended, and null when X shows none. type: object required: [live, broadcast, userId, userName] properties: live: type: boolean description: True while the user's latest broadcast is running. example: false broadcast: anyOf: - $ref: '#/components/schemas/Broadcast' - type: 'null' description: Latest broadcast, live or ended. Null when X shows none. example: id: '1DxLdZyVPMMxm' title: "NASA's SpaceX Crew-12 Re-Entry & Splashdown" state: 'Ended' userId: type: string description: ID of the user. example: '11348282' userName: type: string description: Username of the user. example: NASA example: live: false userId: '11348282' userName: NASA broadcast: id: '1DxLdZyVPMMxm' title: "NASA's SpaceX Crew-12 Re-Entry & Splashdown" state: 'Ended' ProfileTranslation: description: Holds X's translation of 1 profile's bio into the requested language. `entities` holds the links, mentions, and tags with their offsets in the translated text, and is empty when the text has none. type: object required: [userId, userName, language, text, entities] properties: userId: type: string description: ID of the account whose bio X translated. example: '11348282' userName: type: string description: Username of that account. example: NASA language: type: string description: Language code of the translated bio, in lower case. example: es sourceLanguage: type: string description: Language code X detects in the bio, when it names one. example: en text: type: string description: Translated bio. example: 'Haciendo lo aparentemente imposible, posible. ✨' entities: $ref: '#/components/schemas/TweetEntities' example: userId: '11348282' userName: NASA language: es sourceLanguage: en text: 'Haciendo lo aparentemente imposible, posible. ✨' entities: {} TweetUrlEntity: description: Shortened, display, and expanded URLs from tweet text. type: object properties: display_url: { type: string } expanded_url: { type: string } indices: type: array items: *whole-number url: { type: string } TweetUserMention: description: Profile identity and source offsets of a mention. type: object required: [screen_name] properties: id_str: { type: string } indices: type: array items: *whole-number name: { type: string } screen_name: { type: string } TweetNote: description: Complete Note Tweet content and rich-text metadata. type: object required: [text] properties: id: type: string description: X's global ID of the Note, base64 of `NoteTweet:`. noteId: type: string description: The Note's own ID, apart from the post's. example: '2100306607800229889' text: type: string isExpandable: type: boolean entities: $ref: '#/components/schemas/TweetEntities' inlineMedia: type: array description: Inline media positions in the Note Tweet text. items: type: object required: [index, mediaId] properties: index: *whole-number mediaId: { type: string } richtextTags: type: array items: type: object required: [fromIndex, toIndex, types] properties: fromIndex: $ref: '#/components/schemas/WholeNumber' toIndex: $ref: '#/components/schemas/WholeNumber' types: type: array items: type: string TweetPreviousCounts: description: Engagement counts retained from a prior tweet edit. type: object properties: bookmarkCount: $ref: '#/components/schemas/WholeNumber' likeCount: $ref: '#/components/schemas/WholeNumber' quoteCount: $ref: '#/components/schemas/WholeNumber' replyCount: $ref: '#/components/schemas/WholeNumber' retweetCount: $ref: '#/components/schemas/WholeNumber' TweetPoint: description: Author-published geographic point with 2 numeric coordinates. type: object required: [coordinates, type] properties: coordinates: type: array minItems: 2 maxItems: 2 items: { type: number } type: type: string enum: [Point] TweetPlace: description: Public place metadata on a geotagged tweet. type: object properties: boundingBox: $ref: '#/components/schemas/PublicMetadata' country: type: string countryCode: type: string fullName: type: string id: type: string name: type: string placeType: type: string url: type: string NewsVersion: description: 1 version X wrote of a news story. type: object required: [id, createdAt, headline, text] properties: id: type: string description: The version's ID. example: '2110211669641105725' createdAt: type: string format: date-time description: When X wrote the version, in UTC, from its ID. example: '2026-10-14T03:30:42.536Z' headline: type: string description: The story's headline in this version. example: "Elon Musk Pushes Starlink for India's Remote Areas Amid Regulatory Hurdles" text: type: string description: The story's text in this version, without the time line X writes above it in the reader's time zone. example: "Musk has accused Reliance Industries' Mukesh Ambani of blocking Starlink's entry to protect local telecom giants like Jio, while India's government insists on equal treatment for all applicants, including ongoing security reviews. In Vietnam, Starlink already provides free internet to isolated spots for tourism and disaster response, highlighting its potential for hard-to-reach areas. Yet challengers note India's cheap mobile data from Jio and Airtel covers most needs, raising questions on pricing and national security as Starlink seeks final clearances." TrendLocation: description: A place X offers trends for. type: object required: - woeid - name - country - countryCode - placeType - placeTypeCode - parentWoeid - url properties: woeid: type: integer minimum: 1 description: Location ID. Pass it as woeid to /x/trends. example: 2344116 name: type: string example: 'Istanbul' country: type: [string, 'null'] description: Country name. Null for Worldwide. example: 'Turkey' countryCode: type: [string, 'null'] description: 2-letter country code. Null for Worldwide. example: 'TR' placeType: type: [string, 'null'] description: X's kind of place. Town, Country, Supername for Worldwide, or Unknown. example: 'Town' placeTypeCode: type: [integer, 'null'] minimum: 0 description: X's numeric code for the kind of place. example: 7 parentWoeid: type: [integer, 'null'] minimum: 1 description: WOEID of the country or region above it. Null for Worldwide. example: 23424969 url: type: [string, 'null'] description: X's legacy Yahoo GeoPlanet reference. It may not resolve. example: 'http://where.yahooapis.com/v1/place/2344116' example: woeid: 2344116 name: 'Istanbul' country: 'Turkey' countryCode: 'TR' placeType: 'Town' placeTypeCode: 7 parentWoeid: 23424969 url: 'http://where.yahooapis.com/v1/place/2344116' Place: description: A place on X, such as a city or a neighborhood. type: object required: - id - name - fullName - country - countryCode - placeType - url - centroid - boundingBox - attributes properties: id: type: string description: Place ID. Pass it as place to /x/tweets/search. example: '5e02a0f0d91c76d2' name: type: string description: Short name of the place. example: 'İstanbul' fullName: type: [string, 'null'] description: Name with the region or country around the place. example: 'İstanbul, Türkiye' country: type: [string, 'null'] description: Country the place lies in. example: 'Turkey' countryCode: type: [string, 'null'] description: 2-letter code of the country the place lies in. example: 'TR' placeType: type: [string, 'null'] description: X's kind of place, such as city, admin, neighborhood, poi or country. example: 'city' url: type: [string, 'null'] description: X's own reference URL for the place. example: 'https://api.twitter.com/1.1/geo/id/5e02a0f0d91c76d2.json' centroid: type: [array, 'null'] description: Center of the place. Longitude, then latitude. items: { type: number, example: 28.84318392941324 } example: [28.84318392941324, 41.054196399999995] boundingBox: type: [object, 'null'] description: Outline of the place as GeoJSON. Each point holds longitude, then latitude. required: [type, coordinates] properties: type: type: string description: GeoJSON shape of the outline. example: 'Polygon' coordinates: type: array description: Rings of points that draw the outline. items: type: array items: type: array items: { type: number, example: 28.6321043 } example: [28.6321043, 40.8027337] example: [[28.6321043, 40.8027337], [29.3783413, 41.2399073]] example: - - [28.6321043, 40.8027337] - [28.6321043, 41.2399073] - [29.3783413, 41.2399073] - [29.3783413, 40.8027337] example: type: 'Polygon' coordinates: - - [28.6321043, 40.8027337] - [28.6321043, 41.2399073] - [29.3783413, 41.2399073] - [29.3783413, 40.8027337] attributes: type: object $ref: '#/components/schemas/PublicMetadata' description: Extra details X attaches to some places. Often empty. example: id: '5e02a0f0d91c76d2' name: 'İstanbul' fullName: 'İstanbul, Türkiye' country: 'Turkey' countryCode: 'TR' placeType: 'city' url: 'https://api.twitter.com/1.1/geo/id/5e02a0f0d91c76d2.json' centroid: [28.84318392941324, 41.054196399999995] boundingBox: type: 'Polygon' coordinates: - - [28.6321043, 40.8027337] - [28.6321043, 41.2399073] - [29.3783413, 41.2399073] - [29.3783413, 40.8027337] attributes: {} PlaceSearchResult: description: A place X found, with the larger places it lies in. allOf: - $ref: '#/components/schemas/Place' - type: object required: [containedWithin] properties: containedWithin: type: array description: Larger places this place lies in. Often 1. items: $ref: '#/components/schemas/Place' example: [] example: id: '5e02a0f0d91c76d2' name: 'İstanbul' fullName: 'İstanbul, Türkiye' country: 'Turkey' countryCode: 'TR' placeType: 'city' url: 'https://api.twitter.com/1.1/geo/id/5e02a0f0d91c76d2.json' centroid: [28.84318392941324, 41.054196399999995] boundingBox: type: 'Polygon' coordinates: - - [28.6321043, 40.8027337] - [28.6321043, 41.2399073] - [29.3783413, 41.2399073] - [29.3783413, 40.8027337] attributes: {} containedWithin: [] Hashflag: description: A custom emoji X shows after a hashtag for a set time. type: object required: - hashtag - assetUrl - startsAt - endsAt - isHashfettiEnabled - animations properties: hashtag: type: string description: Hashtag text without the hash sign. X also lists some plain phrases. example: 'AION2' assetUrl: type: string format: uri description: Image of the emoji. example: 'https://abs.twimg.com/hashflags/BF-16692_AIon2_jp_Hashmoji_v3/BF-16692_AIon2_jp_Hashmoji_v3.png' startsAt: type: string format: date-time description: When X starts showing the emoji, in UTC. example: '2026-10-02T10:00:00.000Z' endsAt: type: string format: date-time description: When X stops showing the emoji, in UTC. example: '2027-01-03T14:59:00.000Z' isHashfettiEnabled: type: boolean description: Whether X marks the hashflag for its hashfetti effect. example: false animations: type: array description: Animations X plays for the hashtag, such as on a like. Often empty. items: type: object required: [context, assetUrl, priority] properties: context: type: [string, 'null'] description: What plays the animation, such as Like. example: 'Like' assetUrl: type: string format: uri description: Animation file. example: 'https://abs.twimg.com/hashflags/2026FootballCustomLikeEvergreenv3/2026FootballCustomLikeEvergreenv3_sakura_0.json' priority: type: [number, 'null'] description: X's order among the animations of a hashtag. example: 1 example: context: 'Like' assetUrl: 'https://abs.twimg.com/hashflags/2026FootballCustomLikeEvergreenv3/2026FootballCustomLikeEvergreenv3_sakura_0.json' priority: 1 example: [] example: hashtag: 'AION2' assetUrl: 'https://abs.twimg.com/hashflags/BF-16692_AIon2_jp_Hashmoji_v3/BF-16692_AIon2_jp_Hashmoji_v3.png' startsAt: '2026-10-02T10:00:00.000Z' endsAt: '2027-01-03T14:59:00.000Z' isHashfettiEnabled: false animations: [] TweetTombstone: description: Public visibility notice attached to an available tweet. type: object properties: type: { type: string, description: Visibility notice type. } text: type: object properties: text: { type: string, description: Human-readable notice text. } rtl: { type: boolean, description: Right-to-left text direction. } entities: type: array items: type: object properties: fromIndex: *whole-number toIndex: *whole-number ref: type: object properties: type: { type: string } url: { type: string } urlType: { type: string } text: { type: string } screenName: { type: string } TweetInterstitial: description: >- The notice x.com covers the post with until the reader views it, such as X's public interest notice on a post that broke its rules but stays up. type: object properties: displayType: type: string description: How x.com shows the notice. `NonCompliant` marks a post that broke X's rules. example: NonCompliant text: type: object properties: text: type: string description: The notice's text. example: This Post violated the X Rules about glorifying violence. However, X has determined that it may be in the public's interest for the Post to remain accessible. Learn more rtl: { type: boolean, description: Whether X writes it right to left. } entities: type: array description: Links inside the notice, by character range. items: type: object properties: fromIndex: *whole-number toIndex: *whole-number ref: type: object properties: type: { type: string, example: TimelineUrl } url: type: string example: 'https://help.x.com/rules-and-policies/public-interest' urlType: { type: string, example: ExternalUrl } text: { type: string } screenName: { type: string } TweetPublicDataBase: description: >- Public tweet fields, excluding nested tweets. `text` reads as x.com shows it, with `&`, `<` & `>` decoded. `displayTextRange` & entity `indices` count that text. type: object required: - id - text - retweetCount - replyCount - likeCount - quoteCount - viewCount - bookmarkCount properties: id: { type: string, example: '1234567890' } text: { type: string, example: 'Just launched!' } type: { type: string, example: tweet } createdAt: { type: string, example: '2025-01-15T12:00:00Z' } url: type: string example: 'https://x.com/example_user/status/1234567890' lang: { type: string, example: en } isReply: { type: boolean, example: false } isLimitedReply: { type: boolean, example: false } isNoteTweet: { type: boolean, example: false } isPinned: { type: boolean, example: false } isQuoteStatus: { type: boolean, example: false } isRetweet: { type: boolean, example: false } quotedTweetId: { type: string } quotedTweetPermalink: type: object description: The quoted post's link, kept when X withholds that post. properties: displayUrl: { type: string } expandedUrl: { type: string } url: { type: string } quotedTweetUnavailable: type: object description: Why X shows no quoted post. Omitted when X names no reason, as its legacy answers never do. required: [reason] properties: reason: type: string description: X's reason, such as `Suspended` for a suspended author or `Protected` for an author who protects their posts. example: Suspended retweetedAt: type: [string, 'null'] format: date-time description: Repost event time in UTC. Null when unavailable. Omitted for other posts. example: '2026-09-11T20:24:45.000Z' inReplyToId: { type: string, example: '1234567890' } inReplyToUserId: { type: string, example: '9876543210' } inReplyToUsername: { type: string, example: example_user } conversationId: { type: string, example: '1234567890' } conversationControl: type: object description: Reply policy & conversation owner. properties: allowedCountryCodes: type: array description: Regions whose accounts may reply, as country codes. Sent with the `country_of_origin` mode. items: { type: string, example: TR } inviteViaMention: { type: boolean } mode: type: string description: Reply policy from X's newer field, such as `my_network`, `premium` or `country_of_origin`. Omitted when X sends none. example: my_network ownerId: type: string description: The conversation owner's account ID. example: '1902917852849385472' ownerUsername: { type: string } policy: { type: string, example: by_invitation } limitedActions: type: array description: Public restrictions & prompts. items: type: object properties: action: { type: string, example: Reply } prompt: type: object properties: ctaType: { type: string, example: SeeConversation } headline: { type: string } metadata: { $ref: '#/components/schemas/PublicMetadata' } subtext: { type: string } source: type: string description: The app the post was sent from, as X labels it. X sends it for some posts only. example: 'Twitter Web App' displayTextRange: type: array items: *whole-number example: [0, 31] textHighlights: type: array description: Where `text` matches the search, on each row a search read. Offsets count code points of `text`, as `displayTextRange` does. Empty when X marks nothing in the post. X marks matches only in a post's first 280 characters. items: type: object required: [startIndex, endIndex] properties: startIndex: type: integer minimum: 0 description: The first code point of the match. example: 5 endIndex: type: integer minimum: 0 description: The first code point after the match. example: 13 example: [{ startIndex: 5, endIndex: 13 }] contentDisclosure: $ref: '#/components/schemas/ContentDisclosure' article: $ref: '#/components/schemas/TweetArticleMetadata' authorUnavailable: $ref: '#/components/schemas/TweetAuthorUnavailable' unavailableAuthorId: type: string description: The author's ID when X withholds the author's profile. card: $ref: '#/components/schemas/TweetCard' cashtagAttachments: type: array description: > Price charts the author attached under the post, 1 per cashtag. Absent when the post has none. X may send a cashtag without a chart window. items: type: object required: [cashtag] properties: cashtag: type: string description: The cashtag with its `$`. example: $TSLA candleSize: type: string description: Span of each candle. example: 5m timeframe: type: string description: Span the chart covers. example: 1D startTime: type: string format: date-time description: Time of the chart's first candle. example: '2026-10-09T13:30:00.000Z' endTime: type: string format: date-time description: Time of the chart's last price. example: '2026-10-09T13:42:08.796Z' sizeVariant: type: integer minimum: 0 description: X's size for the chart. example: 1 communityId: { type: string, description: Community ID. } communityName: type: string description: Community name. Present when X sends it with the post. example: Build in Public communityNote: $ref: '#/components/schemas/TweetCommunityNote' hasCommunityNotes: type: boolean description: Whether X holds Community Notes on the post, shown or not. edit: $ref: '#/components/schemas/TweetEdit' exclusiveContent: $ref: '#/components/schemas/TweetExclusiveContent' isTranslatable: { type: boolean } grokShareAttachment: $ref: '#/components/schemas/PublicMetadata' grokTranslatedPost: type: object $ref: '#/components/schemas/PublicMetadata' description: Grok's translation of the post, as X shows it. jetfuelAttachment: { $ref: '#/components/schemas/PublicMetadata' } noteTweet: $ref: '#/components/schemas/TweetNote' place: $ref: '#/components/schemas/TweetPlace' coordinates: $ref: '#/components/schemas/TweetPoint' type: object description: Author-published point, with longitude before latitude. geo: $ref: '#/components/schemas/TweetPoint' type: object description: Author-published point, with latitude before longitude. postCta: { $ref: '#/components/schemas/PublicMetadata' } possiblySensitive: { type: boolean } previousCounts: $ref: '#/components/schemas/TweetPreviousCounts' reactionContext: type: object description: Public post & user this reaction references. properties: reactedToPostId: { type: string, description: Referenced post ID. } reactedToUser: { $ref: '#/components/schemas/UserProfile' } sportsContext: type: object description: Game metadata attached to this post. properties: gameId: { type: string, description: Game ID. } league: { type: string, description: League ID. } title: { type: string, description: Game title. } url: { type: string, description: Game link. } state: { type: string, description: Reported game state. } statusText: { type: string, description: Game progress text. } scheduledAtMs: type: [number, string] description: Scheduled Unix milliseconds, retaining the source type. competitors: type: array description: Teams & reported scores. items: type: object properties: teamId: { type: string, description: Team ID. } color: { type: string, description: Team display color. } isActive: { type: boolean, description: Active competitor. } isWinner: { type: boolean, description: Winning competitor. } abbreviation: { type: string, description: Team abbreviation. } name: { type: string, description: Team name. } score: { type: string, description: Score display text. } logoUrl: { type: string, description: Logo for light backgrounds. } darkLogoUrl: { type: string, description: Logo for dark backgrounds. } subscriberBadge: $ref: '#/components/schemas/TweetSubscriberBadge' tombstone: $ref: '#/components/schemas/TweetTombstone' interstitial: $ref: '#/components/schemas/TweetInterstitial' unmentionedUserIds: type: array description: User IDs that left this conversation. items: { type: string } viewState: { type: string } entities: $ref: '#/components/schemas/TweetEntities' scopes: { $ref: '#/components/schemas/PublicMetadata' } media: type: array items: $ref: '#/components/schemas/TweetMedia' description: Media, omitted when unavailable. retweetCount: type: integer minimum: 0 example: 5 replyCount: type: integer minimum: 0 example: 3 likeCount: type: integer minimum: 0 example: 42 quoteCount: type: integer minimum: 0 example: 1 viewCount: type: integer minimum: 0 example: 1500 bookmarkCount: type: integer minimum: 0 example: 2 unknownCounts: type: array uniqueItems: true description: > The counts X did not send for this post. Each one reads 0, so treat it as unknown rather than none. Names follow the response's key style, so `xquik-api-contract: 2026-04-29` lists bookmark_count. Posts from before X counted views, & new posts X has not counted views for yet, list viewCount. Left out when X sent every count. items: type: string enum: [ retweetCount, replyCount, likeCount, quoteCount, viewCount, bookmarkCount, ] example: [bookmarkCount] TweetPublicData: description: Shared public tweet fields. allOf: - $ref: '#/components/schemas/TweetPublicDataBase' - type: object properties: parentTweet: $ref: '#/components/schemas/EmbeddedTweet' quoted_tweet: $ref: '#/components/schemas/EmbeddedTweet' retweeted_tweet: $ref: '#/components/schemas/EmbeddedTweet' EmbeddedTweet: description: A parent, quoted or retweeted tweet. It has the TweetPublicData fields and an author. Nesting stops after 4 levels. allOf: - $ref: '#/components/schemas/TweetPublicDataBase' - type: object properties: author: { $ref: '#/components/schemas/UserProfile' } parentTweet: type: object additionalProperties: true description: The post this one replies to, with the same fields. example: &nestedTweetExample id: '1234567890' text: 'Just launched!' createdAt: '2025-01-15T12:00:00Z' retweetCount: 5 replyCount: 3 likeCount: 42 quoteCount: 1 viewCount: 1500 bookmarkCount: 2 quoted_tweet: type: object additionalProperties: true description: The post this one quotes, with the same fields. example: *nestedTweetExample retweeted_tweet: type: object additionalProperties: true description: The post this one reposts, with the same fields. example: *nestedTweetExample additionalProperties: true ContentDisclosure: description: Content disclosure metadata X shows on a labeled tweet. X labels paid partnership content and AI-generated media. type: object properties: advertising: type: object properties: isPaidPromotion: type: boolean description: True when X labels the tweet as paid promotion content. example: true aiGenerated: type: object properties: detectionSource: type: string description: How X detected AI media. X omits it for self-declared posts. example: GrokSignature hasAiGeneratedMedia: type: boolean description: True when X labels the tweet as containing AI-generated media. example: true TweetDetail: description: Full tweet with text, engagement metrics, media, and metadata. A zero metric can mean X did not report the count. example: bookmarkCount: 661 id: '2102882545427714266' likeCount: 9043 quoteCount: 100 replyCount: 207 retweetCount: 772 text: "Welcome to the Artemis Accords, Croatia 🇭🇷\n \nToday, Croatia became the 74th nation that has committed to a peaceful and prosperous exploration of space. https://t.co/Xe1nm2pkSX https://t.co/QQGjcE6KKq" viewCount: 1291231 conversationId: '2102882545427714266' contentDisclosure: aiGenerated: hasAiGeneratedMedia: false displayTextRange: - 0 - 176 edit: editableUntilMsecs: '1790204843000' editTweetIds: - '2102882545427714266' entities: hashtags: [] urls: - display_url: 'go.nasa.gov/3VcvAQn' expanded_url: 'https://go.nasa.gov/3VcvAQn' indices: - 153 - 176 url: 'https://t.co/Xe1nm2pkSX' user_mentions: [] isNoteTweet: false isPinned: false isQuoteStatus: false isReply: false isRetweet: false isTranslatable: false lang: 'en' possiblySensitive: false source: 'Sprinklr' type: 'tweet' url: 'https://x.com/NASA/status/2102882545427714266' viewState: 'EnabledWithCount' hasCommunityNotes: false media: - altText: 'A graphic showing 74 flags of different countries that have joined the Artemis Accords, now including the Republic of Croatia. Text at the top of the image reads "Artemis Accords," and text at the bottom reads "United for Peaceful Exploration of Deep Space."' availabilityStatus: 'Available' displayUrl: 'pic.x.com/QQGjcE6KKq' expandedUrl: 'https://x.com/NASA/status/2102882545427714266/photo/1' faceRects: large: - h: 72 w: 72 x: 234 'y': 658 - h: 177 w: 177 x: 207 'y': 226 medium: - h: 43 w: 43 x: 140 'y': 394 - h: 106 w: 106 x: 124 'y': 135 orig: - h: 72 w: 72 x: 234 'y': 658 - h: 177 w: 177 x: 207 'y': 226 small: - h: 24 w: 24 x: 79 'y': 223 - h: 60 w: 60 x: 70 'y': 76 focusRects: - h: 1120 w: 2000 x: 0 'y': 0 - h: 1125 w: 1125 x: 875 'y': 0 - h: 1125 w: 987 x: 957 'y': 0 - h: 1125 w: 563 x: 1169 'y': 0 - h: 1125 w: 2000 x: 0 'y': 0 height: 1125 id: '2102882539895468032' indices: - 177 - 200 mediaKey: '3_2102882539895468032' mediaUrl: 'https://pbs.twimg.com/media/HS7wh0rXMAA61bq.jpg' sizes: large: h: 1125 resize: 'fit' w: 2000 medium: h: 675 resize: 'fit' w: 1200 small: h: 383 resize: 'fit' w: 680 thumb: h: 150 resize: 'crop' w: 150 type: 'photo' url: 'https://t.co/QQGjcE6KKq' width: 2000 createdAt: 'Wed Sep 23 22:07:23 +0000 2026' allOf: - $ref: '#/components/schemas/TweetPublicData' - type: object properties: author: $ref: '#/components/schemas/TweetAuthor' ProfileContactInfo: description: Emails, phone numbers & links the account publishes on its own profile. Omitted when it publishes none. type: object properties: emails: type: array description: Emails in the bio, name or location, lowercased. items: type: object required: [value, domain, source] properties: value: type: string description: The email address. example: press@example.com domain: type: string description: The part after the @ sign. example: example.com source: type: string enum: [bio, name, location] description: Profile field that holds the email. writtenAs: type: string description: The account's own spelling, sent when it spelled the email out. example: 'press [at] example [dot] com' phones: type: array description: Phone numbers on the profile. Only a spelling that can be nothing else counts. items: type: object required: [value, source] properties: value: type: string description: The digits, with a leading + when the account wrote a country code. example: '+14155550123' source: type: string enum: [bio, name, location, url] description: Profile field that holds the number. writtenAs: type: string description: The account's own spelling of the number. example: '+1 (415) 555-0123' links: type: array description: The profile's website & the links in its bio. items: type: object required: [url, network, source] properties: url: type: string description: The link, as X expands it. example: https://www.linkedin.com/company/acme network: type: string description: Site the link belongs to, such as `linkedin`, `github` or `telegram`. Any other site is `website`. example: linkedin source: type: string enum: [url, bio] description: '`url` for the website field, `bio` for a bio link.' TweetAuthor: description: Author profile. Lookups always include follower count & verification. Other fields appear when X sends them. example: id: '11348282' username: 'NASA' name: 'NASA' followers: 92376194 following: 115 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' profilePictureOriginal: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' description: 'Making the seemingly impossible, possible. ✨' location: 'Pale Blue Dot' createdAt: 'Wed Dec 19 20:20:32 +0000 2007' statusesCount: 74336 mediaCount: 28160 protected: false url: 'http://www.nasa.gov/' contactInfo: links: - url: 'http://www.nasa.gov/' network: website source: url favouritesCount: 17003 isTranslator: false possiblySensitive: false verifiedType: 'Government' profile_bio: description: 'Making the seemingly impossible, possible. ✨' entities: description: {} url: urls: - display_url: 'nasa.gov' expanded_url: 'http://www.nasa.gov/' indices: - 0 - 23 url: 'https://t.co/9NkQJKAnuU' hasGraduatedAccess: true parodyCommentaryFanLabel: 'None' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileTranslatorType: 'regular' superFollowEligible: false allOf: - $ref: '#/components/schemas/UserProfile' - title: TweetAuthorRequirements type: object required: [followers, verified] properties: followers: type: integer minimum: 0 example: 150000000 verified: *boolean-example-true SearchTweet: description: Search tweet with author. Zero metrics may mean X omitted counts. allOf: - $ref: '#/components/schemas/TweetPublicData' - type: object properties: author: $ref: '#/components/schemas/UserProfile' ReplyTweet: description: Reply row. A reply the post's author hid carries hiddenByAuthor. allOf: - $ref: '#/components/schemas/SearchTweet' - type: object properties: hiddenByAuthor: type: boolean const: true description: Present on a reply the post's author hid. Complete-mode replies carry it when includeHidden asks for them. example: true Space: type: object description: X Space required: [id, admins, speakers, listeners] properties: id: type: string description: Space ID example: '1OGwblLjnQMKB' title: type: string description: Space title example: 'Extending the Network to the Edge' state: type: string description: NotStarted (scheduled), Running (live), Ended, Canceled (scheduled, never started) or TimedOut (closed by X, not by its host) example: 'Ended' createdAt: type: string format: date-time description: When the Space was made example: '2026-03-10T21:49:59.425Z' scheduledStart: type: string format: date-time description: When the Space was set to start example: '2026-03-11T17:00:00.000Z' startedAt: type: string format: date-time description: When the Space went live example: '2026-03-11T17:00:26.227Z' endedAt: type: string format: date-time description: When the Space ended example: '2026-03-11T17:49:29.190Z' updatedAt: type: string format: date-time description: When X last changed the Space example: '2026-03-11T17:49:30.879Z' totalLiveListeners: type: integer minimum: 0 description: Accounts that listened live example: 841 totalReplayWatched: type: integer minimum: 0 description: Accounts that played the recording example: 609 participantCount: type: integer minimum: 0 description: Accounts in the Space now, while it is live example: 67 isAvailableForReplay: type: boolean description: Whether X offers a recording isAvailableForClipping: type: boolean description: Whether listeners may clip the Space isLocked: type: boolean description: Whether the host locked the Space isEmployeeOnly: type: boolean description: Whether only X employees may join disallowJoin: type: boolean description: Whether X lets no more accounts join noIncognito: type: boolean description: Whether anonymous listening is off contentType: type: string description: Audio or video kind, as X names it example: 'visual_audio' conversationControls: type: integer minimum: 0 description: X's code for who may speak example: 0 maxAdminCapacity: type: integer minimum: 0 description: Most hosts and co-hosts the Space allows example: 3 mediaKey: type: string description: X's media key for the Space's audio example: '28_2031487758255214592' mentionedUserIds: type: array description: IDs of the accounts the host tagged items: type: string example: ['379392334'] tweetId: type: string description: ID of the post that announces the Space example: '2031777281509564419' tweet: $ref: '#/components/schemas/SearchTweet' creator: $ref: '#/components/schemas/UserProfile' admins: type: array description: Hosts and co-hosts items: $ref: '#/components/schemas/SpaceParticipant' speakers: type: array description: Accounts X lists as speakers items: $ref: '#/components/schemas/SpaceParticipant' listeners: type: array description: Accounts X lists as listeners items: $ref: '#/components/schemas/SpaceParticipant' sharings: type: array description: Posts the hosts and speakers shared in the Space, in X's order. Present only when X lists them. items: $ref: '#/components/schemas/SpaceSharing' example: - id: '2106511178339881415' sharedAt: '2026-10-03T22:26:16.658Z' updatedAt: '2026-10-03T22:26:16.658Z' sharedBy: id: '3259467336' username: 'JoeCarlasare' name: 'Joe Carlasare' tweet: id: '2105620368836706789' text: 'Yields are rising in Europe as well.' retweetCount: 35 replyCount: 32 likeCount: 275 quoteCount: 8 viewCount: 98007 bookmarkCount: 20 SpaceSharing: description: A post shared in a Space, & the account that shared it. type: object properties: id: type: string description: X's ID of the sharing, not of the post example: '2106511178339881415' sharedAt: type: string format: date-time description: When the post was shared example: '2026-10-03T22:26:16.658Z' updatedAt: type: string format: date-time description: When X last changed the sharing example: '2026-10-03T22:26:16.658Z' sharedBy: $ref: '#/components/schemas/UserProfile' tweet: $ref: '#/components/schemas/SearchTweet' Broadcast: type: object description: X broadcast, a live video required: [id] properties: id: type: string description: Broadcast ID example: '1nGeLMWbkpaKX' title: type: string description: Broadcast title example: 'USSF-259 Mission' isTitleEdited: type: boolean description: Whether the broadcaster edited the title of the replay state: type: string description: State, such as NotStarted, Running or Ended, as X names it example: 'Ended' scheduledStart: type: string format: date-time description: When the broadcast was set to start example: '2026-09-17T00:55:00.000Z' startedAt: type: string format: date-time description: When the broadcast went live example: '2026-09-17T00:54:56.506Z' endedAt: type: string format: date-time description: When the broadcast ended example: '2026-09-17T01:17:35.036Z' lastPingAt: type: string format: date-time description: When the video stream last reached X example: '2026-09-17T01:17:32.232Z' totalWatched: type: integer minimum: 0 description: Accounts that watched, live or after example: 161758 totalWatching: type: integer minimum: 0 description: Accounts watching, as X counts them example: 21639 isAvailableForReplay: type: boolean description: Whether X offers a recording of the broadcast width: type: integer minimum: 0 description: Video width in pixels example: 3840 height: type: integer minimum: 0 description: Video height in pixels example: 2160 cameraRotation: type: integer minimum: 0 maximum: 359 description: Camera rotation in degrees example: 0 isHighLatency: type: boolean description: Whether the video stream runs in high-latency mode chatOption: type: integer minimum: 0 description: X's code for who may chat example: 1 isPrivateChat: type: boolean description: Whether X marks the chat private source: type: string description: What produced the video stream, as X names it example: 'LiveCms' mediaKey: type: string description: X's media key for the video example: '28_2097700444252635136' preLiveSlateUrl: type: string format: uri description: Image X shows before the broadcast starts example: 'https://pbs.twimg.com/media/HRyHXi3WoAAYJ6F.jpg' version: type: integer minimum: 0 description: X's revision number of the broadcast example: 151 tweetId: type: string description: ID of the post that announces the broadcast example: '2106868248524542376' tweet: $ref: '#/components/schemas/SearchTweet' periscopeUser: type: object description: Broadcaster, as X's live video service names the account properties: id: type: string description: Live video account ID example: '1raQZonlMGYKz' username: type: string description: Live video username example: 'SpaceX' displayName: type: string description: Live video display name example: 'SpaceX' profilePicture: type: string format: uri description: Live video avatar URL profilePictureOriginal: type: string format: uri description: The broadcaster's avatar at full size creator: $ref: '#/components/schemas/UserProfile' SpaceParticipant: description: An account on a Space's stage or in its audience, as X lists it there. type: object required: [id, username, name] properties: id: *user-id-example-schema username: *username-example-schema name: type: string description: Name the account shows in the Space example: 'Solana' profilePicture: type: string description: Profile picture URL example: 'https://pbs.twimg.com/profile_images/example_normal.jpg' profilePictureOriginal: type: string description: The participant's profile picture at full size example: 'https://pbs.twimg.com/profile_images/example.jpg' isVerified: type: boolean description: Whether X shows a verified badge in the Space isBlueVerified: type: boolean description: Whether the account has X Premium verification verifiedType: type: string description: Business or Government badge type example: 'Business' affiliatesHighlightedLabel: $ref: '#/components/schemas/UserAffiliateLabel' joinedAt: type: string format: date-time description: When the account joined the Space example: '2026-03-11T17:00:52.759Z' isMutedByAdmin: type: boolean description: Whether a host muted the account isMutedByGuest: type: boolean description: Whether the account muted itself periscopeUserId: type: string description: The account's ID in X's broadcast service example: '645158' UserAffiliateLabel: description: Organization affiliation label shown on an X profile. type: object properties: badgeUrl: type: string description: type: string longDescription: type: object $ref: '#/components/schemas/PublicMetadata' description: Public text, ranges, references, and mention data. url: type: string urlType: type: string userLabelDisplayType: type: string userLabelType: type: string UserHighlightsInfo: description: Profile highlight availability and count metadata. type: object properties: canHighlightTweets: type: boolean highlightedTweets: type: string UserIdentityVerification: description: Identity verification X shows on the profile & its About page. type: object properties: description: { type: string } isIdentityVerified: type: boolean description: Whether the owner verified their ID with X. overrideVerifiedYear: type: integer minimum: 1 maximum: 9999 description: The year X shows as the start of verification, in place of verifiedSinceMsec. example: 2009 verifiedSinceMsec: type: string description: When X verified the account, in milliseconds since 1970, as text. example: '1507188387580' UserTipJar: description: Public payment and creator-support handles shown on X. type: object properties: bandcampHandle: { type: string } bitcoinHandle: { type: string } cashAppHandle: { type: string } ethereumHandle: { type: string } gofundmeHandle: { type: string } isEnabled: { type: boolean } patreonHandle: { type: string } payPalHandle: { type: string } venmoHandle: { type: string } CommunityPage: description: 1 page of X Communities, in X's order. type: object required: [communities, has_next_page, next_cursor] properties: communities: type: array description: Communities in X's order items: $ref: '#/components/schemas/Community' example: *community-rows-example has_next_page: type: boolean description: Whether another page of communities follows example: true next_cursor: type: string description: Cursor for the next page of communities. Empty at the end. example: 'WzM1LjUxMjQ5N10=' CommunityAnalyticsMetric: description: A community metric for X's latest period & its percent change. type: object required: [count, changePercent] properties: count: type: integer minimum: 0 description: Total for this metric during X's latest period. example: 15298 changePercent: type: number description: Change in percent from the same figure 1 day earlier. Values stay unrounded. example: -1.2076202776880853 CommunityAnalytics: description: Community activity & growth for X's latest period. type: object required: [id, periodEndsAt, metrics] properties: id: type: string description: The community ID from your request. example: '1493446837214187523' periodEndsAt: type: string format: date-time description: The end of X's latest period, in UTC. example: '2026-10-16T23:59:59.999Z' metrics: type: object description: The period's activity, each metric with its count and changePercent. likes counts likes on community posts and newMembers the accounts that joined. posts counts the community posts and replies the replies to them. uniquePosters counts the distinct accounts that posted. required: [likes, newMembers, posts, replies, uniquePosters] example: likes: count: 15298 changePercent: -1.2076202776880853 newMembers: count: 557 changePercent: -1.5901060070671376 posts: count: 5108 changePercent: 0.5907837731390311 replies: count: 6851 changePercent: -0.8251302837290099 uniquePosters: count: 1800 changePercent: -0.33222591362126247 properties: likes: $ref: '#/components/schemas/CommunityAnalyticsMetric' newMembers: $ref: '#/components/schemas/CommunityAnalyticsMetric' posts: $ref: '#/components/schemas/CommunityAnalyticsMetric' replies: $ref: '#/components/schemas/CommunityAnalyticsMetric' uniquePosters: $ref: '#/components/schemas/CommunityAnalyticsMetric' Community: description: Public X Community, as every Community read returns it. type: object required: [id, name, member_count, is_nsfw] example: id: '1493446837214187523' name: 'Build in Public' member_count: 268126 is_nsfw: false banner: url: 'https://pbs.twimg.com/community_banner_img/1915033378811772928/KdaKUaRP?format=png&name=orig' width: 805 height: 322 colors: - percentage: 42.48 red: 247 green: 228 blue: 29 - percentage: 42.48 red: 0 green: 0 blue: 1 - percentage: 9.57 red: 64 green: 58 blue: 13 - percentage: 4.43 red: 167 green: 154 blue: 27 - percentage: 0.75 red: 219 green: 219 blue: 219 focus: left: 403 top: 161 width: 1 height: 1 description: "Share what you're working on. Get feedback. Help each other move forward. – Sponsored by bolt.new ⚡" created_at: '1644900447551' join_policy: 'Open' invites_policy: 'MemberInvitesAllowed' banner_url: 'https://pbs.twimg.com/community_banner_img/1915033378811772928/KdaKUaRP?format=png&name=orig' moderator_count: 6 primary_topic: id: '603' name: 'Entrepreneurship' question: 'What are you working on?' rules: - description: "Don't be scared to share unfinished work" id: '1493447542045958144' name: "Share what you're working on" - description: "Visual tweets tend to grab people's attention" id: '1493448150169755648' name: 'Screenshots, screencasts, drafts, etc' - description: "Don't ask for upvotes or advertise your products/services." id: '1836095088465781029' name: 'No self-promotion' - description: 'Only post about building in public. No politics or other off-topic posts. There are other communities for that.' id: '1836095194716066104' name: 'Stay on-topic' - description: 'If your goal is to get replies, likes, etc, don''t post it here. Don''t ask super generic questions like "what''s everyone working on?"' id: '1836095002557944207' name: 'No engagement farming' - description: 'No company accounts. No logos. Use your own name. No promotion or URLs in your name.' id: '1836094745590059481' name: 'Use a personal account' searchTags: - 'buildinpublic' - 'buildinginpublic' - 'builtinpublic' admin: &community-admin-example id: '641633' username: 'marckohlbrugge' name: 'Marc Köhlbrugge' followers: 89054 following: 973 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1857124042433572864/iMivVaYP_normal.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/641633/1781378883' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/641633/1781378883' description: '🚧 https://t.co/aMZ4K3azU0 🏠 https://t.co/1KH3Ex4L2r 🤑 https://t.co/z2G662Uvhl 👀 https://t.co/LtA0MMRVNA 🚀 https://t.co/sxmNUGTYQv 📣 https://t.co/oPODwYE4Iq 💻 https://t.co/leziY51tRd 📸 https://t.co/NJnFBXCSCj #️⃣ https://t.co/6qUnpK7VH5' createdAt: 'Mon Jan 15 23:55:33 +0000 2007' statusesCount: 50114 mediaCount: 4890 protected: false url: 'https://wip.co/@marc' favouritesCount: 37854 possiblySensitive: false pinnedTweetIds: - '2105016385931989045' verifiedType: 'Blue' profile_bio: description: '🚧 https://t.co/aMZ4K3azU0 🏠 https://t.co/1KH3Ex4L2r 🤑 https://t.co/z2G662Uvhl 👀 https://t.co/LtA0MMRVNA 🚀 https://t.co/sxmNUGTYQv 📣 https://t.co/oPODwYE4Iq 💻 https://t.co/leziY51tRd 📸 https://t.co/NJnFBXCSCj #️⃣ https://t.co/6qUnpK7VH5' entities: description: urls: - display_url: 'wip.co' expanded_url: 'http://wip.co' indices: - 2 - 25 url: 'https://t.co/aMZ4K3azU0' - display_url: 'roomai.com' expanded_url: 'http://roomai.com' indices: - 28 - 51 url: 'https://t.co/1KH3Ex4L2r' - display_url: 'highscore.money' expanded_url: 'http://highscore.money' indices: - 54 - 77 url: 'https://t.co/z2G662Uvhl' - display_url: 'loot.photos' expanded_url: 'http://loot.photos' indices: - 80 - 103 url: 'https://t.co/LtA0MMRVNA' - display_url: 'betalist.com' expanded_url: 'http://betalist.com' indices: - 106 - 129 url: 'https://t.co/sxmNUGTYQv' - display_url: 'submit.co' expanded_url: 'http://submit.co' indices: - 132 - 155 url: 'https://t.co/oPODwYE4Iq' - display_url: 'startup.jobs' expanded_url: 'http://startup.jobs' indices: - 158 - 181 url: 'https://t.co/leziY51tRd' - display_url: 'yay.camera' expanded_url: 'http://yay.camera' indices: - 184 - 207 url: 'https://t.co/NJnFBXCSCj' - display_url: 'buildinpublic.com' expanded_url: 'http://buildinpublic.com' indices: - 212 - 235 url: 'https://t.co/6qUnpK7VH5' url: urls: - display_url: 'wip.co/@marc' expanded_url: 'https://wip.co/@marc' indices: - 0 - 23 url: 'https://t.co/QVn818Sinw' hasGraduatedAccess: true professional: category: [] professional_type: 'Creator' rest_id: '1458256691506683904' profileDescriptionLanguage: 'en' profileImageShape: 'Circle' profileTranslatorType: 'none' superFollowEligible: true creator: *community-admin-example membersFacepile: - *community-admin-example properties: id: type: string description: Unique community identifier name: type: string description: Display name of the community description: type: string description: About text for the community member_count: type: integer minimum: 0 description: Total member count moderator_count: type: integer minimum: 0 description: Total moderator count is_nsfw: type: boolean description: Whether the community is marked sensitive primary_topic: type: object description: Primary topic. Its id is absent when X lists the community in a keyword or topic result. required: [name] properties: id: type: string description: Topic ID that /x/communities/popular takes name: type: string description: Topic name X shows on the community created_at: type: string description: Community creation timestamp join_policy: type: string description: Join policy (open or restricted) invites_policy: type: string description: Invitation policy question: type: string description: What the community asks a user who joins example: 'What are you working on?' rules: type: array description: Community rules items: type: object properties: id: type: string description: Rule ID name: type: string description: Rule title description: type: string description: What the rule asks of members searchTags: type: array description: Tags X finds the community by items: type: string example: ['buildinpublic'] creator: description: The creator's public profile, or the ID, username and badge alone when X sends no profile anyOf: - $ref: '#/components/schemas/UserProfile' - type: object required: [id, username, verified] properties: id: type: string description: Numeric X user ID of the creator username: type: string description: X username of the creator verified: type: boolean description: Whether X shows the creator a badge admin: $ref: '#/components/schemas/UserProfile' membersFacepile: type: array description: The members X previews beside the member count. A keyword or topic result gives each member's ID & picture only. items: anyOf: - $ref: '#/components/schemas/UserProfile' - $ref: '#/components/schemas/CommunityMemberPreview' banner_url: type: string description: Community banner image URL banner: $ref: '#/components/schemas/CommunityBanner' CommunityBanner: description: The banner X shows for a community, with its size & colors. type: object required: [url] properties: url: type: string description: Banner image URL at its original size width: type: integer minimum: 0 description: Banner width in pixels height: type: integer minimum: 0 description: Banner height in pixels colors: type: array description: Main colors of the banner, largest share first items: type: object required: [percentage, red, green, blue] properties: percentage: type: number minimum: 0 description: Share of the banner in this color red: type: integer minimum: 0 maximum: 255 description: Red value of the color green: type: integer minimum: 0 maximum: 255 description: Green value of the color blue: type: integer minimum: 0 maximum: 255 description: Blue value of the color focus: type: object description: Area X keeps in view when it crops the banner, in pixels from the top left properties: left: type: integer minimum: 0 description: Distance from the left edge top: type: integer minimum: 0 description: Distance from the top edge width: type: integer minimum: 0 description: Width of the area height: type: integer minimum: 0 description: Height of the area CommunityMemberPreview: description: A member X previews by ID & profile picture only. type: object required: [id] properties: id: type: string description: Numeric X user ID of the member profilePicture: type: string description: Profile picture URL of the member profilePictureOriginal: type: string description: The member's profile picture at full size CommunityTopic: description: A topic X groups communities under, with its subtopics. type: object required: [id, name, subtopics] properties: id: type: string description: Topic ID. Pass it as topicId to /x/communities/popular. name: type: string description: Topic name, which topic on /x/communities/popular takes subtopics: type: array description: Narrower topics inside this topic items: type: object required: [id, name] properties: id: type: string description: Subtopic ID, which topicId also takes name: type: string description: Subtopic name, which topic also takes AccountBasedIn: description: >- X's best-effort public label inferred from aggregated account-access IP addresses. It does not state nationality, residence, identity, registration, post location, or exact location. type: object required: [value, level, observedAt] properties: value: { type: string, example: United States } level: { type: string, enum: [country, region], example: country } observedAt: { type: string, format: date-time, example: '2026-08-21T10:00:00Z' } UserProfile: description: Public X profile. type: object example: id: '11348282' username: 'NASA' name: 'NASA' followers: 92376187 accountBasedIn: null following: 115 verified: true isBlueVerified: true isVerified: true profilePicture: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB_normal.jpg' profilePictureOriginal: 'https://pbs.twimg.com/profile_images/1321163587679784960/0ZxKlEKB.jpg' coverPicture: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' profileBannerUrl: 'https://pbs.twimg.com/profile_banners/11348282/1788992290' description: 'Making the seemingly impossible, possible. ✨' location: 'Pale Blue Dot' createdAt: 'Wed Dec 19 20:20:32 +0000 2007' birthdate: day: 1 month: 10 year: 1958 statusesCount: 74336 mediaCount: 28160 protected: false url: 'http://www.nasa.gov/' contactInfo: links: - url: 'http://www.nasa.gov/' network: website source: url favouritesCount: 17003 possiblySensitive: false verifiedType: 'Government' profile_bio: description: 'Making the seemingly impossible, possible. ✨' entities: description: {} url: urls: - display_url: 'nasa.gov' expanded_url: 'http://www.nasa.gov/' indices: - 0 - 23 url: 'https://t.co/9NkQJKAnuU' businessAccountAffiliatesCount: 85 creatorSubscriptionsCount: 0 hasGraduatedAccess: true hasHiddenSubscriptionsOnProfile: false highlightsInfo: canHighlightTweets: true highlightedTweets: '280' identityVerification: isIdentityVerified: false verifiedSinceMsec: '1249674830941' isProfileTranslatable: false parodyCommentaryFanLabel: 'None' profileDescriptionLanguage: 'en' profileImageShape: 'Square' profileSortEnabled: true profileTranslatorType: 'regular' superFollowEligible: false verificationReason: entities: - fromIndex: 91 toIndex: 101 url: 'https://help.twitter.com/en/rules-and-policies/profile-labels' urlType: 'ExternalUrl' text: 'This account is verified because it is a government or multilateral organization account. Learn more' required: [id, username, name] properties: id: *user-id-example-schema username: *username-example-schema name: type: string example: 'Elon Musk' description: type: string example: 'CEO of Tesla, SpaceX, and X' followers: type: integer minimum: 0 description: Omitted when X sends no count, as for the account that first posted reused media. example: 150000000 following: type: integer minimum: 0 example: 500 verified: *boolean-example-true isBlueVerified: type: boolean description: Whether X shows a blue verification badge example: true isVerified: type: boolean description: Whether X marks the profile as verified example: true profilePicture: type: string description: Profile picture at 48 px, as X sends it. example: 'https://pbs.twimg.com/profile_images/example_normal.jpg' profilePictureOriginal: type: string description: The same profile picture at full size, as the account uploaded it. Download this one for the image. example: 'https://pbs.twimg.com/profile_images/example.jpg' coverPicture: type: string example: 'https://pbs.twimg.com/profile_banners/example.jpg' profileBannerUrl: type: string description: Original X profile banner field when available example: 'https://pbs.twimg.com/profile_banners/example.jpg' location: type: string description: Account owner's public profile location text example: 'Austin, TX' accountBasedIn: description: Null when X shows no label. anyOf: - $ref: '#/components/schemas/AccountBasedIn' - type: 'null' accountBasedInUnavailable: type: boolean description: True when X withheld accountBasedIn from this read. Retry later. accountBasedInAccurate: type: boolean description: False when X notes accountBasedIn may be inaccurate. connectedVia: type: string description: How the account first connected to X. example: United States App Store connectedViaAccurate: type: boolean description: False when X notes that country may be inaccurate. affiliateUsername: type: string description: Handle of the organization X shows the account is affiliated with, from its About page. example: BBCNews email: type: string description: First email the account publishes on its profile, lowercased. Omitted when it publishes none. example: press@example.com contactInfo: $ref: '#/components/schemas/ProfileContactInfo' usernameChanges: type: object description: How often the account changed its username. required: [count] properties: count: *whole-number lastChangedAt: type: string format: date-time description: Time of the latest change, omitted when there is none. example: '2016-05-14T00:22:47.057Z' birthdate: type: object description: The parts of the birthday the account made public. properties: day: { type: integer, minimum: 1, maximum: 31 } month: { type: integer, minimum: 1, maximum: 12 } year: { type: integer, minimum: 1, maximum: 9999 } retweetedAt: type: [string, 'null'] format: date-time description: UTC repost time with includeRetweetTimestamp. Null if the newest profile page has no match or lookup failed. Otherwise omitted. example: '2026-09-11T20:24:45.000Z' createdAt: type: string example: '2009-06-02T20:12:29Z' description: Account creation time. statusesCount: type: integer minimum: 0 example: 35000 mediaCount: type: integer minimum: 0 example: 1200 protected: type: boolean description: Whether the profile protects its posts example: false url: type: string example: 'https://xquik.com' favouritesCount: type: integer minimum: 0 example: 18000 hasCustomTimelines: *boolean-example-true isTranslator: *boolean-example-false withheldInCountries: type: array items: type: string example: ['DE'] withheldScope: type: string description: Whether X withholds a post or user example: user possiblySensitive: *boolean-example-false professional: type: object $ref: '#/components/schemas/PublicMetadata' description: Professional metadata with category display settings grokTranslatedBio: type: object $ref: '#/components/schemas/PublicMetadata' description: Public profile bio translation returned by X pinnedTweetIds: type: array items: type: string example: ['1234567890'] isAutomated: *boolean-example-false automatedBy: type: string example: 'example_user' unavailable: *boolean-example-false unavailableReason: type: string example: 'suspended' verifiedType: type: string example: 'Business' affiliatesHighlightedLabel: $ref: '#/components/schemas/UserAffiliateLabel' businessAccountAffiliatesCount: $ref: '#/components/schemas/WholeNumber' creatorSubscriptionsCount: $ref: '#/components/schemas/WholeNumber' hasGraduatedAccess: type: boolean hasHiddenSubscriptionsOnProfile: type: boolean highlightsInfo: $ref: '#/components/schemas/UserHighlightsInfo' identityVerification: $ref: '#/components/schemas/UserIdentityVerification' isProfileTranslatable: type: boolean parodyCommentaryFanLabel: type: string profileDescriptionLanguage: type: string profileImageShape: type: string profileInterstitialType: type: string profileSortEnabled: type: boolean profileTranslatorType: type: string redirectsToUsername: type: string description: Handle x.com sends this profile's visitors to, such as the new handle of a renamed account whose old handle now holds a placeholder. Missing when x.com shows the profile itself. example: spacexsi superFollowEligible: type: boolean superFollowsUserProfileActive: type: boolean description: Whether X marks the subscription profile as active. tipJar: $ref: '#/components/schemas/UserTipJar' listedCount: type: integer minimum: 0 description: Public lists that include the profile. example: 3051 fastFollowersCount: type: integer minimum: 0 description: Followers X counts as fast followers. normalFollowersCount: type: integer minimum: 0 description: Followers minus fast followers. defaultProfile: type: boolean description: Whether the profile keeps X's default theme. defaultProfileImage: type: boolean description: Whether the profile keeps X's default avatar. hasExtendedProfile: type: boolean description: Whether the profile filled X's extended fields, such as a birth date. True or false. isTranslationEnabled: type: boolean description: Whether the account turned on X's translation of its posts. True or false. geoEnabled: type: boolean description: Whether the profile may add a location to posts. advertiserAccountType: type: string description: The account's X Ads type. `none` for an account without ads, or `promotable_user` for one that may run them. example: none advertiserAccountServiceLevels: type: array description: X Ads services the account uses, such as `analytics`, `media_studio` or `smb`. Empty for an account without ads. items: type: string businessProfileState: type: string description: Whether X treats the profile as a business profile. `none` or `enabled`. example: none subscribersCount: type: integer minimum: 0 description: Accounts subscribed to the profile's paid Subscriptions. 0 when it has none. verificationReason: type: object description: X's text on why the profile is verified, with its links. properties: text: type: string example: This account is verified because it's an official organization on X. entities: type: array description: Links inside the text, by character range. items: type: object properties: fromIndex: *whole-number toIndex: *whole-number url: { type: string } urlType: { type: string } communityRole: type: string description: Community role when returned by community member reads example: Member profile_bio: type: object $ref: '#/components/schemas/PublicMetadata' description: Structured profile bio with entity annotations example: description: CEO of Tesla, SpaceX, and X entities: urls: [] # ── New schemas ────────────────────────────────────────── Draft: description: Private Xquik draft with optional topic and goal. type: object required: [id, text, createdAt] properties: id: *resource-id-example-schema text: type: string example: 'Draft tweet about AI trends' topic: type: string example: 'Technology' goal: type: string example: 'Engagement' createdAt: *created-at-schema IgnoredFieldsNotice: description: The fields a write did not read, when the request sent any. type: object properties: ignoredFields: type: array items: type: string description: Fields the request sent that this route does not read, in the order sent. They changed nothing. The answer leaves this out when the route read every field. example: [plan] DraftDetail: description: Full private Xquik draft including update timestamp. allOf: - $ref: '#/components/schemas/Draft' - type: object required: [updatedAt] properties: updatedAt: *update-time-example-schema StyleProfileSummary: description: Style profile summary with tweet count and ownership flag. type: object required: [xUsername, tweetCount, isOwnAccount, fetchedAt] properties: xUsername: *username-example-schema tweetCount: type: integer minimum: 0 example: 50 isOwnAccount: *boolean-example-true fetchedAt: &creation-time-example-schema type: string format: date-time example: '2025-01-15T12:00:00Z' StyleProfile: description: Full style profile with sampled tweets used for tone analysis. example: *style-profile-example allOf: - $ref: '#/components/schemas/StyleProfileSummary' - type: object required: [tweets] properties: tweets: type: array items: type: object required: [id, text] properties: id: *tweet-id-example-schema text: type: string example: 'Just launched our new feature!' createdAt: *timestamp-text-example-schema authorUsername: *username-example-schema example: - id: '1234567890' text: *launch-text RadarItem: description: Trending topic with score, category, source, region, language, and source-specific metadata. type: object required: - id - sourceId - title - score - category - source - region - language - metadata - publishedAt - createdAt properties: id: type: string description: Radar item identifier. example: '4712' sourceId: type: string description: Source-specific identifier used for deduplication. example: 'trustmrr_acme' title: type: string example: 'AI Revolution in 2025' url: type: string example: 'https://example.com/article/ai-revolution' score: type: number example: 95.5 category: type: string enum: *radar-category-values example: 'tech' source: type: string enum: *radar-source-values example: 'trustmrr' region: type: string example: 'global' language: type: string example: 'en' description: BCP-47 language code. und means the source did not identify a language. metadata: type: object description: | Source fields vary. - reddit has author, authorId?, subreddit, subredditId?, subredditSubscribers?, sourceFormat, score?, upvoteRatio?, estimatedUpvotes?, estimatedDownvotes?, numberComments?, numberCrossposts?, selftext?, contentUrl?, domain?, postHint?, linkFlairText?, distinguished?, totalAwardsReceived?, viewCount?, editedAt?, galleryImageUrls?, redditVideo?, archived?, contestMode?, isCrosspostable?, isMeta?, isNsfw?, isOriginalContent?, isRobotIndexable?, isSelf?, isSpoiler?, isVideo?, locked? & stickied?. - github has starsToday. - hacker_news has points & numberComments. - google_trends has approxTraffic. - polymarket has volume24hr. - wikipedia has views. - trustmrr has mrr, growthPercent, last30Days, total, customers, activeSubscriptions, onSale, xHandle?, category?, askingPrice?, country?, foundedDate?, googleSearchImpressionsLast30Days?, growthMrrPercent?, multiple?, paymentProvider?, profitMarginLast30Days?, rank?, revenuePerVisitor?, targetAudience? & visitorsLast30Days?. Reddit score is public net. Vote estimates use its fuzzed ratio. Comments are omitted. Startup xHandle omits @. rank is its growth rank. properties: author: type: string contentUrl: *uri-string estimatedDownvotes: *nonnegative-integer estimatedUpvotes: *nonnegative-integer numberComments: *nonnegative-integer score: type: integer minimum: -9007199254740991 selftext: type: string sourceFormat: type: string enum: [html, json, rss] description: Current items use html. json and rss remain on legacy rows. subreddit: type: string upvoteRatio: type: number minimum: 0 maximum: 1 additionalProperties: true publishedAt: *creation-time-example-schema createdAt: type: string format: date-time example: '2025-01-15T12:01:00Z' description: type: string example: 'AI is transforming every industry' imageUrl: type: string description: Source image. Startup growth items return the logo here. example: 'https://example.com/images/ai.jpg' XAccount: description: Linked X account summary with connection status, health, and timestamp metadata. type: object required: [id, xUserId, xUsername, status, health, createdAt, updatedAt] properties: id: *resource-id-example-schema xUserId: *user-id-example-schema xUsername: *username-example-schema status: type: string example: 'active' health: type: string description: > Derived health. `healthy` is ready. `needsReauth` needs credentials. `locked` needs an unlock on X. `suspended` is banned. `recovering` can reconnect. Wait before using `temporaryIssue`. enum: &account-health-values [ healthy, locked, needsReauth, recovering, suspended, temporaryIssue, ] example: 'healthy' createdAt: *created-at-schema updatedAt: &account-update-time-example-schema type: string format: date-time example: '2025-03-10T08:30:00Z' connectedAt: type: string format: date-time description: When the account last connected or reconnected. example: '2025-03-10T08:30:00Z' XAccountConnectionChallenge: description: Resumable account connection challenge. Submit the email code to finish the same connection attempt. type: object required: [object, id, status, expiresAt, message, username] properties: object: type: string const: x_account_connection_challenge example: 'x_account_connection_challenge' id: type: string example: 'xch_8vGd8Y9JvH6dV0xA' status: type: string const: requires_email_code example: 'requires_email_code' expiresAt: type: string format: date-time example: '2026-05-08T12:10:00Z' message: type: string example: 'Enter the email verification code to continue.' username: *username-example-schema XAccountConnectionContinuation: description: The connection is still running or needs an email code. example: { object: x_account_connection_attempt, id: xatt_0123456789abcdef0123456789abcdef, status: pending, pollAfterMs: 3000, } oneOf: - $ref: '#/components/schemas/XAccountConnectionAttemptPending' - $ref: '#/components/schemas/XAccountConnectionChallenge' discriminator: propertyName: status mapping: pending: '#/components/schemas/XAccountConnectionAttemptPending' requires_email_code: '#/components/schemas/XAccountConnectionChallenge' XAccountConnectionAttemptPending: description: The connection is still in progress. type: object additionalProperties: false required: [object, id, status, pollAfterMs] properties: object: &connection-attempt-type type: string const: x_account_connection_attempt example: 'x_account_connection_attempt' id: type: string example: 'xatt_0123456789abcdef0123456789abcdef' status: type: string const: pending example: 'pending' pollAfterMs: type: integer minimum: 0 example: 3000 XAccountConnectionAttemptSuccess: description: The account connected. type: object additionalProperties: false required: [object, id, status] properties: object: *connection-attempt-type id: type: string example: 'xatt_0123456789abcdef0123456789abcdef' status: type: string const: success example: 'success' XAccountConnectionAttemptFailed: description: The connection reached a final failure. type: object additionalProperties: false required: [object, id, status, error, retryable] properties: object: *connection-attempt-type id: type: string example: 'xatt_0123456789abcdef0123456789abcdef' status: type: string const: failed example: 'failed' error: type: string example: 'service_unavailable' reason: type: string example: 'wrong_password' retryable: *boolean-example-true XAccountDetail: description: Connected X account details with health and timestamp metadata. type: object required: [id, xUserId, xUsername, status, health, createdAt] properties: id: *resource-id-example-schema xUserId: *user-id-example-schema xUsername: *username-example-schema status: type: string example: 'active' health: &x-account-health-schema type: string enum: *account-health-values example: 'healthy' createdAt: *created-at-schema updatedAt: *account-update-time-example-schema connectedAt: type: string format: date-time description: Last connection or reconnection time of this account. Omitted before its first login. example: '2025-03-10T08:30:00Z' SanitizedXAccount: description: Sanitized X account summary returned by connect and reauth. type: object required: [id, xUserId, xUsername, status, health, createdAt] properties: id: *resource-id-example-schema xUserId: *user-id-example-schema xUsername: *username-example-schema status: type: string const: active example: 'active' health: *x-account-health-schema createdAt: *created-at-schema XAccountBody: description: Request body identifying an X account by username or ID. type: object required: [account] properties: account: type: string maxLength: 64 description: X account identifier (@username or account ID) example: '@elonmusk' TweetAnalysisRequest: description: Posts to analyze & optional analysis settings. Send tweetIds, texts, or a search, never more than 1. A search is query, username, listId, quotesOf or repliesTo, alone or together, & sinceTime & untilTime narrow it. type: object additionalProperties: false example: query: 'Sony WH-1000XM6 lang:en' limit: 20 analysis: targets: [{ name: 'Sony', aliases: ['WH-1000XM6'] }] properties: tweetIds: type: array minItems: 1 maxItems: 100 description: Post IDs or post URLs to analyze, up to 100. example: ['1893456789012345678'] items: type: string maxLength: 2048 example: '1893456789012345678' query: type: string minLength: 1 maxLength: 4096 description: X search to analyze, with the operators of /x/tweets/search, such as from:nasa or lang:en. X searches up to 512 characters, counted with the other search fields, as /x/tweets/search counts q. example: 'Sony WH-1000XM6 lang:en' username: type: string minLength: 1 maxLength: 2048 description: Analyze 1 account's posts. Send a handle, with or without @, or a profile URL. example: '@NASA' listId: type: string minLength: 1 maxLength: 2048 description: Analyze a public List's posts. Send its ID or URL. example: '1234567890' quotesOf: type: string minLength: 1 maxLength: 2048 description: Analyze the quotes of 1 post. Send its ID or URL. example: '1893456789012345678' repliesTo: type: string minLength: 1 maxLength: 2048 description: Analyze the replies in 1 post's conversation. Send its ID or URL. example: '1893456789012345678' sinceTime: type: [string, integer] minLength: 1 maxLength: 64 minimum: 0 description: Inclusive start of the search, such as 2026-09-25T00:00:00Z. Unix seconds also work. A time without an offset is UTC. example: '2026-09-25T00:00:00Z' untilTime: type: [string, integer] minLength: 1 maxLength: 64 minimum: 0 description: Exclusive end of the search, such as 2026-09-26T00:00:00Z. Unix seconds also work. A time without an offset is UTC. example: '2026-09-26T00:00:00Z' queryType: type: string enum: [Latest, Top] description: Search order. Default Latest. example: 'Latest' limit: type: integer minimum: 1 maximum: 100 default: 20 description: Maximum posts to analyze from the search. A low credit balance can return fewer. example: 20 cursor: type: string minLength: 1 maxLength: 4096 description: The next_cursor of the page before. Send the same search with it. example: 'DAACCgACGRElMJcAAA' texts: type: array minItems: 1 maxItems: 100 description: Your own texts to analyze, such as drafts. Reads nothing from X. Each text costs the same as 1 analyzed post. example: ['We shipped dark mode today. Tell us what breaks.'] items: type: string minLength: 1 maxLength: 64000 example: 'We shipped dark mode today. Tell us what breaks.' analysis: $ref: '#/components/schemas/TweetAnalysisSettings' baseline: type: array maxItems: 10000 description: Rows of an earlier answer to compare with, such as its results. Each needs the post's id, or tweet.id, & its answers. Send monitor too, so other settings show as not_comparable. Each result's monitor says whether the post is new, changed or unchanged. The comparison costs nothing extra. example: - id: '1893456789012345678' answers: { sentiment: 'positive', intensity: 1, sarcasm: 0.04 } items: type: object required: [answers] properties: id: type: string minLength: 1 maxLength: 19 description: Post ID, or text:1 & so on. Otherwise tweet.id counts. example: '1893456789012345678' tweet: type: object required: [id] properties: id: { type: string, minLength: 1, maxLength: 19, example: '1893456789012345678', } answers: type: object description: The earlier answers by question ID. additionalProperties: type: [string, number] maxLength: 7821 example: 'positive' example: { sentiment: 'positive', intensity: 1 } monitor: type: object description: The earlier row's monitor, with its fingerprint. properties: configurationFingerprint: type: string maxLength: 64 example: '9f2c4e1b7a5d3c8e6f0a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f6a' TweetAnalysisSettings: description: Analysis settings, the same as the analysis input of Xquik's AI Actors. Leave it out for the route's own questions. type: object additionalProperties: false example: targets: [{ name: 'Sony', aliases: ['WH-1000XM6'] }] context: 'Consumer headphones & customer service.' properties: questions: type: array minItems: 1 maxItems: 8 description: Your own questions, which replace the route's questions. Write question IDs & category names in lower case without hyphens. example: - id: 'request' type: 'choice' version: '1' instructions: 'What does the author ask for?' categories: support: 'Help with a problem.' recommendation: 'Advice on choosing a product.' other: 'Neither request.' items: $ref: '#/components/schemas/TweetAnalysisQuestion' preset: type: string enum: - brand - complaints - competitors - purchase_intent - product_feedback - news - sentiment - market - viral_lite description: A ready set of questions, used when questions is left out. complaints, competitors, purchase_intent & product_feedback need targets. viral_lite scores how viral the wording reads. example: 'complaints' targets: type: array maxItems: 100 description: Brands, people, assets or topics the questions are about, each with its aliases. example: [{ name: 'Sony', aliases: ['WH-1000XM6'] }] items: type: object additionalProperties: false required: [name] example: { name: 'Sony', aliases: ['WH-1000XM6'] } properties: name: type: string minLength: 1 maxLength: 63757 example: 'Sony' aliases: type: array maxItems: 100 example: ['WH-1000XM6'] items: type: string minLength: 1 maxLength: 63754 example: 'WH-1000XM6' context: type: string maxLength: 63781 description: Background the AI reads with every post. example: 'Consumer headphones & customer service.' maxContextBytes: type: integer minimum: 219 maximum: 64000 default: 64000 description: Bytes of post, quote & settings the AI reads. Xquik cuts longer posts to fit. Empty settings take 219 bytes, so a smaller value gets a 400. example: 64000 concurrency: type: integer minimum: 1 maximum: 16 default: 16 description: Posts analyzed at the same time. example: 16 TweetAnalysisQuestion: description: A question the AI answers for each post. A choice picks 1 of 2 to 255 categories, a score picks 1 of 2 or more ordered levels & a probability answers yes or no. type: object additionalProperties: false required: [id, type, version, instructions] example: id: 'request' type: 'choice' version: '1' instructions: 'What does the author ask for?' categories: support: 'Help with a problem.' recommendation: 'Advice on choosing a product.' other: 'Neither request.' properties: id: type: string pattern: '^[a-z][a-z0-9_]*$' maxLength: 7852 description: Name of the answer, such as request. A name the response renames or drops gets a 400, such as created_at, favorite_count, muting or blocking. example: 'request' type: type: string enum: [choice, score, probability] example: 'choice' version: type: string minLength: 1 maxLength: 100 description: Your version of the question, such as 1. example: '1' instructions: type: string minLength: 1 maxLength: 7852 description: The question, as the AI reads it. example: 'What does the author ask for?' categories: type: object description: For a choice. Each category name with its description, or null. additionalProperties: type: [string, 'null'] maxLength: 7821 example: 'Help with a problem.' example: support: 'Help with a problem.' other: 'Neither request.' levels: type: array minItems: 2 maxItems: 100 description: For a score. Each level's description, lowest first. example: ['No urgency.', 'Some urgency.', 'Urgent.'] items: type: string minLength: 1 maxLength: 7830 example: 'No urgency.' criteria: type: object additionalProperties: false required: ['yes', 'no'] description: For a probability. What counts as yes & as no. example: { 'yes': 'Asks for a refund.', 'no': 'Asks for no refund.' } properties: 'yes': type: string minLength: 1 maxLength: 7816 example: 'Asks for a refund.' 'no': type: string minLength: 1 maxLength: 7816 example: 'Asks for no refund.' TweetAnalysisPage: description: Analyzed posts, the posts without an analysis & the totals of the answers. Each row in results costs 2 credits. type: object required: [results, unanalyzed, analysisSummary, has_next_page, next_cursor] properties: results: type: array description: Each analyzed post with its answers. example: [] items: $ref: '#/components/schemas/TweetAnalysisResult' unanalyzed: type: array description: Each post without an analysis, by ID & reason. These cost nothing. example: - id: '1893456789012345679' status: 'skipped' reason: 'post_unavailable' items: $ref: '#/components/schemas/UnanalyzedTweet' analysisSummary: $ref: '#/components/schemas/TweetAnalysisSummary' has_next_page: type: boolean description: Whether the search has more posts. Send next_cursor as cursor. example: false next_cursor: type: string description: Cursor of the search's next page, else empty. example: '' TweetAnalysisResult: description: 1 analyzed post with its answers. type: object required: [tweet, analysis, answers, sourceDomains, cashtags, monitor] properties: tweet: type: object description: The post, as /x/tweets/search returns it. Your own texts have the IDs text:1, text:2 & so on. $ref: '#/components/schemas/SearchTweet' analysis: type: object description: The answers in full, with their probabilities. required: - status - answers - questions - contextBytes - contextAvailability properties: status: type: string const: succeeded example: 'succeeded' answers: type: array description: 1 answer per question, in question order. items: $ref: '#/components/schemas/TweetAnalysisAnswer' questions: type: array description: The ID & version of each question asked. items: type: object required: [id, version] properties: id: { type: string, example: 'sentiment' } version: { type: string, example: 'sentiment:2' } contextBytes: type: integer minimum: 0 description: Bytes of post & settings the AI read. example: 612 contextAvailability: type: object description: What the AI read beside the post's text. required: [quote, reply, author, media, article, postText] properties: quote: type: string enum: [available, missing, not_applicable] example: 'not_applicable' reply: type: string enum: [available, missing, not_applicable] example: 'not_applicable' author: type: string enum: [available, missing] example: 'available' media: type: string enum: [text_descriptions_only, not_supplied] example: 'not_supplied' article: type: string enum: [text_blocks, summary, not_supplied] example: 'not_supplied' postText: type: string enum: [full, truncated] description: truncated when the post was cut to fit. example: 'full' answers: type: object description: Each question's decision by question ID. A choice gives its category, a score its level from 0, which can have decimals, & a probability its value from 0 to 1. additionalProperties: type: [string, number] example: 'negative' example: { sentiment: 'negative', intensity: 1.86, sarcasm: 0.08 } sourceDomains: type: array description: Hostnames the post links to, without t.co. example: ['youtube.com'] items: { type: string, example: 'youtube.com' } cashtags: type: array description: Cashtags in the post's text, in upper case. example: ['$NVDA'] items: { type: string, example: '$NVDA' } viralScore: type: [integer, 'null'] minimum: 0 maximum: 100 description: Only from /x/analysis/viral-score. How viral the wording reads, or null when a trait has no answer. example: 72 viralVerdict: type: [string, 'null'] enum: [send_it, edit_first, sleep_on_it, null] description: Only from /x/analysis/viral-score. send_it from 70, edit_first from 40, else sleep_on_it. example: 'send_it' viralAlgorithmScore: type: [number, 'null'] minimum: 0 description: Only from /x/analysis/viral-score. The post's public counts under X's published ranking weights, per 1,000 views or followers. example: 18.4 viralActualEngagementRate: type: [number, 'null'] minimum: 0 description: Only from /x/analysis/viral-score. log10 of 1 plus the weighted engagement per 1,000 followers. Null without a follower count. example: 1.2874 viral: type: object description: Only from /x/analysis/viral-score. The score with its weights version, the caps that applied & the engagement comparison. additionalProperties: true example: score: 72 verdict: 'send_it' weights: 'viral_lite:1' stops: [] algorithmScore: 18.4 algorithmBasis: 'views' algorithmWeightedSum: 412 actualEngagementRate: 1.2874 weightsVersion: 'x_algorithm_params:2026-10-14' monitor: $ref: '#/components/schemas/TweetAnalysisComparison' TweetAnalysisComparison: description: How the post's answers compare with its row in baseline, as the AI Actors compare a run with an earlier dataset. type: object required: - configurationFingerprint - baselineDatasetId - status - changedQuestionIds - changes properties: configurationFingerprint: type: string description: Hash of the questions, targets & context. Rows with another hash are not_comparable. example: '9f2c4e1b7a5d3c8e6f0a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f6a' baselineDatasetId: type: 'null' description: Always null. The baseline is the rows you sent. example: null status: type: string enum: [ first_run, new_to_baseline, unchanged, changed, not_comparable, analysis_unavailable, ] description: first_run without baseline. new_to_baseline for a post baseline lacks. changed when an answer clearly left its earlier decision. not_comparable when other settings made the earlier row or it answers none of these questions. example: 'changed' changedQuestionIds: type: array description: IDs of the questions whose decision changed. example: ['sentiment'] items: { type: string, example: 'sentiment' } changes: type: array description: Each changed decision, earlier & now. items: type: object required: [questionId, previous, current] properties: questionId: { type: string, example: 'sentiment' } previous: { type: string, example: 'positive' } current: { type: string, example: 'negative' } TweetAnalysisAnswer: description: 1 question's answer. A probability has probability. A choice or score has value, confidence & the probability of each category or level. type: object required: [questionId, questionVersion, type] example: questionId: 'sentiment' questionVersion: 'sentiment:2' type: 'choice' value: 'negative' confidence: 0.93 probabilities: { positive: 0.01, negative: 0.93, mixed: 0.04, neutral: 0.01, unclear: 0.01, } properties: questionId: { type: string, example: 'sentiment' } questionVersion: { type: string, example: 'sentiment:2' } type: type: string enum: [choice, score, probability] example: 'choice' value: type: [string, number] description: The chosen category, or the level from 0, which can have decimals, such as 1.4 between levels 1 & 2. example: 'negative' confidence: type: number minimum: 0 maximum: 1 example: 0.93 probabilities: type: object description: Probability of each category, or of each level by index. additionalProperties: type: number minimum: 0 maximum: 1 example: 0.93 example: { positive: 0.01, negative: 0.93, mixed: 0.04, neutral: 0.01, unclear: 0.01, } levels: type: array description: For a score. The levels the question named, from 0. example: ['No attitude.', 'A measured attitude.', 'An emphatic attitude.'] items: { type: string, example: 'No attitude.' } probability: type: number minimum: 0 maximum: 1 description: For a probability. The chance the answer is yes. example: 0.08 UnanalyzedTweet: description: A post without an analysis. It costs nothing. type: object required: [id, status, reason] properties: id: type: string description: Post ID. Your own texts have the IDs text:1, text:2 & so on. example: '1893456789012345678' status: type: string enum: [failed, skipped] example: 'skipped' reason: type: string description: post_unavailable when X returns no such post. missing_text for a post without text. insufficient_credits when credits ran out. context_limit when the settings leave the post no room. The other reasons mean the analysis failed. Send the post again. example: 'post_unavailable' TweetAnalysisSummary: description: Totals of the answers across the analyzed posts. type: object required: - schemaVersion - rows - engagement - questions - targets - cashtags - sourceDomains - monitor properties: schemaVersion: type: integer minimum: 1 example: 1 rows: type: object description: Posts by analysis outcome. required: [analyzed, failed, skipped] properties: analyzed: { type: integer, minimum: 0, example: 20 } failed: { type: integer, minimum: 0, example: 0 } skipped: { type: integer, minimum: 0, example: 0 } engagement: type: integer minimum: 0 description: Likes, reposts, replies & quotes of the analyzed posts. example: 1840 questions: type: object description: Totals by question ID. A choice has counts, shares, engagementShares & top posts per category. A score has mean, engagementWeightedMean & levels. A probability has mean, yes & no. additionalProperties: type: object additionalProperties: true example: type: 'choice' counts: { positive: 12, negative: 5, mixed: 1, neutral: 2, unclear: 0 } example: sentiment: type: 'choice' counts: { positive: 12, negative: 5, mixed: 1, neutral: 2, unclear: 0 } shares: { positive: 0.6, negative: 0.25, mixed: 0.05, neutral: 0.1, unclear: 0, } targets: type: array description: Mentions & answers per target in analysis.targets. items: type: object required: [name, mentions, share, engagement, choices, top] properties: name: { type: string, example: 'Sony' } mentions: { type: integer, minimum: 0, example: 14 } share: { type: number, minimum: 0, maximum: 1, example: 0.7 } engagement: { type: integer, minimum: 0, example: 1200 } choices: type: object description: Category counts by question ID. additionalProperties: true example: { sentiment: { positive: 9, negative: 5 } } top: type: object description: The most engaged posts per question ID & category. additionalProperties: true example: sentiment: negative: [{ tweetId: '1893456789012345678', engagement: 412 }] cashtags: type: array description: Posts & answers per cashtag, most posts first, up to 20. signal is present for the market questions. items: type: object required: [cashtag, rows, choices] properties: cashtag: { type: string, example: '$NVDA' } rows: { type: integer, minimum: 0, example: 3 } choices: type: object description: Category counts of the cashtag's posts by question ID. additionalProperties: true example: { stance: { bullish: 2, bearish: 1 } } signal: type: object required: [bullish, bearish, score] properties: bullish: { type: integer, minimum: 0, example: 2 } bearish: { type: integer, minimum: 0, example: 1 } score: type: number minimum: -1 maximum: 1 description: Bullish minus bearish posts, over all posts. example: 0.3333 sourceDomains: type: array description: Posts per linked hostname, most posts first, up to 20. items: type: object required: [domain, posts] properties: domain: { type: string, example: 'youtube.com' } posts: { type: integer, minimum: 0, example: 4 } viral: type: object description: Only from /x/analysis/viral-score. Scored posts, the average score, verdict counts, the scores against actual engagement, a report per author & the leaderboards. additionalProperties: true example: weights: 'viral_lite:1' scored: 20 unscored: 0 averageScore: 58 verdicts: { send_it: 6, edit_first: 9, sleep_on_it: 5 } monitor: type: [object, 'null'] description: Posts per comparison status, & up to 50 changed posts with their changes. Null when the answer holds no post. required: [statuses, changedRows] properties: statuses: type: object description: Posts per monitor status. additionalProperties: { type: integer, minimum: 0, example: 3 } example: { unchanged: 17, changed: 2, new_to_baseline: 1 } changedRows: type: array items: type: object required: [tweetId, changes] properties: tweetId: { type: string, example: '1893456789012345678' } changes: type: array items: type: object required: [questionId, previous, current] properties: questionId: { type: string, example: 'sentiment' } previous: { type: string, example: 'positive' } current: { type: string, example: 'negative' }