{
  "openapi": "3.1.0",
  "info": {
    "title": "TwitterAPIs API",
    "version": "1.0.0",
    "description": "REST API for Twitter and X data. Search tweets and users, resolve a single tweet into its full thread, read profiles and timelines, page the follower graph, and run write actions over plain HTTP with Bearer auth and JSON. Pay per call: almost every call is $0.0008 (standard reads plus simple write actions like, retweet, bookmark, follow, their undos, and delete), tweet/thread is $0.004, full tweet history is $0.0024, tweet creation and DM reads are $0.0016, and account reads are free. New accounts start with $0.50 in free credits."
  },
  "servers": [
    {
      "url": "https://api.twitterapis.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Your API account: credit balance, usage totals, and payment history. Served from the API root (https://api.twitterapis.com/account/*), not under /twitter, because billing owns their authentication. Free."
    },
    {
      "name": "Account Session",
      "description": "Bring your own X session cookies (recommended), or mint a session from a username and password, so write actions and private-data reads act as your account. Free."
    },
    {
      "name": "Search",
      "description": "Full-text and structured search across tweets and users. Filter by query operators, author, date, language, and engagement."
    },
    {
      "name": "Tweet Details",
      "description": "Resolve a single tweet into its full object: replies, retweeters, and the complete conversation thread."
    },
    {
      "name": "User Reads",
      "description": "Read a profile, its timeline, media, mentions, affiliates, and follow relationships by username or numeric ID."
    },
    {
      "name": "Direct Messages",
      "description": "Read your account's DM inbox and the message history of a single conversation, and send new messages, all acting as the account behind your registered session."
    },
    {
      "name": "Follower Graph",
      "description": "Page through followers and following lists, including the verified-only and v2 cursor-paginated variants."
    },
    {
      "name": "List Data",
      "description": "Read the members of any public Twitter/X List."
    },
    {
      "name": "Trends",
      "description": "Read what is trending on Twitter/X right now, worldwide or for a single country, plus the full set of locations trends are available for."
    },
    {
      "name": "Spaces",
      "description": "Read an X Space by id: title, host, speakers, topics, timing and audience counts, for a Space that is scheduled, running or already ended."
    },
    {
      "name": "Communities",
      "description": "Read an X Community: its metadata and rules, its member and moderator rosters, its own post timeline including the pinned post, and the inverse relation, every community a given account belongs to. These are pooled reads served by our account pool, so the four fields that describe the CALLER's own relationship to a community (role, can_join, is_pinned, viewer_relationship_type) always come back null."
    },
    {
      "name": "Write Actions",
      "description": "Act on behalf of an authenticated account: like, retweet, bookmark, and follow, each with its undo. Billed at $0.0008 per call, the same as a standard read."
    },
    {
      "name": "Articles",
      "description": "Create, edit, publish, and read X's long-form Articles (X's internal name: Notes). Publishing posts a real announcement tweet; reading a published article is a public call that needs no session."
    },
    {
      "name": "Grok",
      "description": "Ask X's own in-app Grok a question and get the answer back with the pages it cited. Grok reads X in real time, so it answers about posts and accounts a general model has never seen. Runs as your account, returns one buffered JSON document rather than a stream, and stores nothing: you pass prior turns back yourself."
    },
    {
      "name": "Monitoring",
      "description": "Watch an X account for new posts and get them pushed to your own webhook, HMAC-signed, retried for 21 minutes on failure. Polls on a shared interval and never spends your read credits: monitor and webhook management are free account administration, not metered reads."
    }
  ],
  "paths": {
    "/account/me": {
      "get": {
        "operationId": "account-me",
        "summary": "Account Info",
        "description": "Returns the account behind your API key: remaining credits, credits consumed, total requests served, and when the account was created. Use it to show a balance in your own dashboard or to alert before you run out of credits. This call is free and is not metered. Cost: Free per call.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/account/me\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/account/me\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/account/me\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Your credit balance, lifetime usage, and account details for the API key making the call.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "email": {
                      "type": "string",
                      "description": "Email address on the account."
                    },
                    "name": {
                      "type": "string",
                      "description": "Account holder name."
                    },
                    "credits_remaining": {
                      "type": "object",
                      "description": "Credits currently available, in USD.",
                      "additionalProperties": true
                    },
                    "credits_used": {
                      "type": "object",
                      "description": "Total credits consumed to date, in USD.",
                      "additionalProperties": true
                    },
                    "total_requests": {
                      "type": "object",
                      "description": "Total number of API requests served for this account.",
                      "additionalProperties": true
                    },
                    "created_at": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of when the account was created."
                    }
                  }
                },
                "example": {
                  "email": "you@example.com",
                  "name": "Your Name",
                  "credits_remaining": 946.4048,
                  "credits_used": 454.1516,
                  "total_requests": 622007,
                  "created_at": "2026-01-14T09:22:31.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://api.twitterapis.com"
        }
      ]
    },
    "/account/payments": {
      "get": {
        "operationId": "account-payments",
        "summary": "Payment History",
        "description": "Returns the payment history for the account behind your API key, ordered newest first. Each entry records what was paid, how many credits it added, and whether the payment completed. Use it to reconcile top-ups against your own billing records. This call is free. Cost: Free per call.",
        "tags": [
          "Account"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/account/payments\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/account/payments\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/account/payments\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Every credit top-up on your account, newest first, with amount, credits added, and status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "payments": {
                      "type": "object",
                      "description": "Payment records, newest first. Empty when the account has never topped up.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "payments": [
                    {
                      "amount": 100,
                      "credits_added": 100,
                      "status": "completed",
                      "created_at": "2026-06-02T14:08:55.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://api.twitterapis.com"
        }
      ]
    },
    "/twitter/customer/session": {
      "post": {
        "operationId": "customer-session",
        "summary": "Register Session",
        "description": "Register your X session cookies so write actions (like, retweet, bookmark, follow, create or delete a tweet) and private-data reads (home timeline, bookmarks, likes, DMs, followers-you-know) run as your account. Supply auth_token and ct0 once; the session is stored against your API key and applied automatically. This call is free. Cost: Free per call.",
        "tags": [
          "Account Session"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/customer/session\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"auth_token\": \"abc123...\", \"ct0\": \"def456...\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/customer/session\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"auth_token\": \"abc123...\", \"ct0\": \"def456...\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/customer/session\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ auth_token: \"abc123...\", ct0: \"def456...\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Register your auth_token and ct0 cookies once so every write and private read acts as your account, or pass them per call as x-auth-token / x-ct0 headers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the session is stored."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable confirmation."
                    },
                    "username": {
                      "type": "string",
                      "description": "The X handle resolved from the session, or null when it could not be resolved."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "message": "Session registered. Private-data endpoints will read as your account.",
                  "username": "myhandle"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "auth_token": {
                    "type": "string",
                    "description": "The auth_token cookie value from a logged-in x.com browser session."
                  },
                  "ct0": {
                    "type": "string",
                    "description": "The ct0 CSRF cookie value from the same x.com browser session."
                  },
                  "user_agent": {
                    "type": "string",
                    "description": "Browser user-agent to send with session requests. Defaults to a current Chrome UA if omitted."
                  },
                  "proxy_url": {
                    "type": "string",
                    "description": "HTTP or SOCKS proxy URL the session egresses through, for example http://user:pass@host:port. This is a property of the session, so every call made with this API key on this session uses it, reads as well as writes. Defaults to direct, which means we choose the egress."
                  }
                },
                "required": [
                  "auth_token",
                  "ct0"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/customer/session/delete": {
      "post": {
        "operationId": "customer-session-delete",
        "summary": "Revoke Session",
        "description": "Delete the X session cookies stored against your API key. The key is taken from the authenticated request, and the handler reads no identity from the body, the query string, or any second header, so a call can only ever remove the caller's own stored session. It is idempotent and answers 200 whether or not a row was there to remove. This call is free. Cost: Free per call.",
        "tags": [
          "Account Session"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/customer/session/delete\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/customer/session/delete\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/customer/session/delete\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Delete the auth_token and ct0 you registered, so we no longer hold your X session cookies. Self-serve, idempotent, and free.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Always true. The request was accepted and no stored session for your API key remains."
                    },
                    "deleted": {
                      "type": "boolean",
                      "description": "True when a stored session was found and removed. False when nothing was stored for this API key, for example after an earlier revoke, or when you only ever sent per-call x-auth-token and x-ct0 credentials."
                    },
                    "message": {
                      "type": "string",
                      "description": "Human-readable confirmation. The wording differs depending on whether a stored session was removed."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "deleted": true,
                  "message": "Your stored Twitter session was deleted. The auth_token and ct0 you registered are no longer on our servers. This does not log the account out of x.com: to invalidate the cookies themselves, revoke the session from your X account settings as well."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/tweet/advanced_search": {
      "get": {
        "operationId": "tweet-advanced-search",
        "summary": "Advanced Tweet Search",
        "description": "Run a full-text tweet search using the same operator syntax as Twitter/X advanced search. Combine free text with operators such as from:, to:, since:, until:, min_faves:, and lang: to filter precisely. Results are cursor-paginated at roughly 20 tweets per call. Cost: $0.0008 per call.",
        "tags": [
          "Search"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/advanced_search?query=from%3Anaval%20min_faves%3A1000&product=Latest\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/advanced_search\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"query\": \"from:naval min_faves:1000\", \"product\": \"Latest\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/advanced_search\");\nurl.search = new URLSearchParams({ query: \"from:naval min_faves:1000\", product: \"Latest\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/tweet/advanced_search?query=from:naval&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/tweet/advanced_search\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"query\": \"from:naval\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { query: \"from:naval\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/tweet/advanced_search\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Search tweets with Twitter's full query-operator syntax, paginated with cursors.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "query": {
                      "type": "string",
                      "description": "Echo of the query you sent."
                    },
                    "product": {
                      "type": "string",
                      "description": "Echo of the ranking product applied to the search."
                    },
                    "tweets": {
                      "type": "array",
                      "description": "Matching tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "query": "from:naval min_faves:1000",
                  "product": "Latest",
                  "count": 20,
                  "next_cursor": "DAABCgABF...",
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "Reading > scrolling. Build the input, the output takes care of itself.",
                      "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                      "author": {
                        "id": "745273",
                        "username": "naval",
                        "name": "Naval"
                      },
                      "favorite_count": 4821,
                      "retweet_count": 612,
                      "reply_count": 88,
                      "quote_count": 14,
                      "bookmark_count": 203,
                      "view_count": 219340
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Search query using Twitter operator syntax.",
            "schema": {
              "type": "string",
              "description": "Search query using Twitter operator syntax.",
              "example": "from:naval min_faves:1000"
            },
            "example": "from:naval min_faves:1000"
          },
          {
            "name": "product",
            "in": "query",
            "required": false,
            "description": "Ranking and result type: Latest, Top, People, Photos, or Videos. Defaults to Latest.",
            "schema": {
              "type": "string",
              "description": "Ranking and result type: Latest, Top, People, Photos, or Videos. Defaults to Latest.",
              "example": "Latest"
            },
            "example": "Latest"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Accepted but not honoured on this endpoint: the upstream page is fixed at roughly 20 results and raising count does not return more. Use cursor to read further.",
            "schema": {
              "type": "integer",
              "description": "Accepted but not honoured on this endpoint: the upstream page is fixed at roughly 20 results and raising count does not return more. Use cursor to read further.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/search": {
      "get": {
        "operationId": "user-search",
        "summary": "User Search",
        "description": "Search the user directory by keyword. Matches against display name, handle, and bio. Useful for discovery, lead lists, and resolving partial handles into full profiles. Cost: $0.0008 per call.",
        "tags": [
          "Search"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/search?query=machine%20learning\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/search\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"query\": \"machine learning\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/search\");\nurl.search = new URLSearchParams({ query: \"machine learning\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Find users by keyword across display names, handles, and bios.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Matching user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk",
                      "description": "",
                      "followers_count": 211000000,
                      "verified": true
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Keyword or partial handle to search for.",
            "schema": {
              "type": "string",
              "description": "Keyword or partial handle to search for.",
              "example": "machine learning"
            },
            "example": "machine learning"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/tweet/detail": {
      "get": {
        "operationId": "tweet-detail",
        "summary": "Tweet Detail",
        "description": "Resolve a tweet ID into its complete object, including author, engagement counts, attached media, and any quoted tweet. The starting point for any single-tweet workflow. Cost: $0.0008 per call.",
        "tags": [
          "Tweet Details"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/detail?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/detail\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/detail\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a single tweet's full object by ID.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Echo of the tweet ID you requested."
                    },
                    "tweet": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Tweet"
                        }
                      ],
                      "description": "The resolved tweet object."
                    }
                  }
                },
                "example": {
                  "id": "1759123456789012345",
                  "tweet": {
                    "id": "1759123456789012345",
                    "text": "Shipping the new docs today.",
                    "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                    "author": {
                      "id": "745273",
                      "username": "naval",
                      "name": "Naval"
                    },
                    "favorite_count": 4821,
                    "retweet_count": 612,
                    "reply_count": 88,
                    "quote_count": 14,
                    "bookmark_count": 203,
                    "view_count": 219340
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to fetch. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to fetch. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet, for example https://x.com/naval/status/1759123456789012345. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet, for example https://x.com/naval/status/1759123456789012345. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          }
        ]
      }
    },
    "/twitter/tweet/replies": {
      "get": {
        "operationId": "tweet-replies",
        "summary": "Tweet Replies",
        "description": "Fetch the direct replies to a given tweet, cursor-paginated. Combine with Tweet Detail to reconstruct a discussion or measure reply sentiment. Cost: $0.0008 per call.",
        "tags": [
          "Tweet Details"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/replies?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/replies\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/replies\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the replies to a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Reply tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "DAABCgABF...",
                  "tweets": [
                    {
                      "id": "1759123999000111222",
                      "text": "Congrats on the launch!",
                      "created_at": "Tue Feb 20 14:30:02 +0000 2026",
                      "author": {
                        "id": "9921",
                        "username": "devjane",
                        "name": "Jane"
                      },
                      "favorite_count": 12,
                      "reply_count": 1
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the parent tweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the parent tweet. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the parent tweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the parent tweet. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          }
        ]
      }
    },
    "/twitter/tweet/retweeters": {
      "get": {
        "operationId": "tweet-retweeters",
        "summary": "Tweet Retweeters",
        "description": "Fetch the users who retweeted a given tweet, cursor-paginated. Useful for amplification analysis and identifying the accounts that spread a post. Cost: $0.0008 per call.",
        "tags": [
          "Tweet Details"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/retweeters?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/retweeters\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/retweeters\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List the users who retweeted a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Users who retweeted, for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "9921",
                      "username": "devjane",
                      "name": "Jane",
                      "followers_count": 4200,
                      "verified": false
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/tweet/quotes": {
      "get": {
        "operationId": "tweet-quotes",
        "summary": "Tweet Quotes",
        "description": "Fetch the quote tweets of a given tweet, cursor-paginated as full tweet objects, so you can read the commentary people attached rather than just count it. This endpoint is search-backed rather than served by a dedicated X operation, and every response says so in-band via source, search_query and quote_matched. Cost: $0.0008 per call.",
        "tags": [
          "Tweet Details"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/quotes?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/quotes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/quotes\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/tweet/quotes?id=1759123456789012345&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/tweet/quotes\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"id\": \"1759123456789012345\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { id: \"1759123456789012345\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/tweet/quotes\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the tweets that quote a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Quote tweets for this page, as full tweet objects. Each one that X embedded the original on carries the requested tweet under quoted_tweet.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of tweets returned in this page. This is what the SEARCH returned, never the tweet's true quote total, which is quote_count on the tweet object (see Tweet Detail). The two will differ because of search-index lag and because deleted, protected and withheld quotes are not in the index."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Pass it straight back as ?cursor=. Null when there is no further page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned tweets and carried a usable next_cursor. False on the final page."
                    },
                    "source": {
                      "type": "string",
                      "description": "Always \"search\". Present so a caller comparing these numbers against X's UI knows this endpoint is served by X's search index and not by a dedicated quote-tweets operation."
                    },
                    "search_query": {
                      "type": "string",
                      "description": "The exact query sent upstream, quoted_tweet_id:<id>, so a surprising result is debuggable without reading our source."
                    },
                    "quote_matched": {
                      "type": "integer",
                      "description": "How many of the returned tweets demonstrably quote the requested id, read off each tweet's embedded quoted_tweet. Equal to count means every row is a genuine quote. Zero on a non-empty page means X stopped honouring the search operator and the rows are junk that merely contain the number."
                    }
                  }
                },
                "example": {
                  "count": 2,
                  "next_cursor": "DAADDAABCgABF...",
                  "has_more": true,
                  "tweets": [
                    {
                      "id": "1759987654321098765",
                      "text": "This is the clearest write-up of the problem I have read all year.",
                      "created_at": "Tue Feb 20 16:02:11 +0000 2026",
                      "author": {
                        "id": "9921",
                        "username": "devjane",
                        "name": "Jane"
                      },
                      "is_quote": true,
                      "quoted_tweet": {
                        "id": "1759123456789012345",
                        "text": "Launching today."
                      },
                      "favorite_count": 41
                    },
                    {
                      "id": "1759988812345678901",
                      "text": "Adding one caveat to this.",
                      "created_at": "Tue Feb 20 16:20:44 +0000 2026",
                      "author": {
                        "id": "3310",
                        "username": "buildlogs",
                        "name": "Build Logs"
                      },
                      "is_quote": true,
                      "quoted_tweet": {
                        "id": "1759123456789012345",
                        "text": "Launching today."
                      },
                      "favorite_count": 7
                    }
                  ],
                  "source": "search",
                  "search_query": "quoted_tweet_id:1759123456789012345",
                  "quote_matched": 2
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet whose quotes you want. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet whose quotes you want. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet whose quotes you want. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet whose quotes you want. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to request for this page. Defaults to 20 and is clamped to 1-100 by the underlying search, so a larger number returns at most 100 rather than erroring.",
            "schema": {
              "type": "integer",
              "description": "Max items to request for this page. Defaults to 20 and is clamped to 1-100 by the underlying search, so a larger number returns at most 100 rather than erroring.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "product",
            "in": "query",
            "required": false,
            "description": "Search ordering: Latest (default, reverse-chronological) or Top (X's ranked ordering, materially slower upstream). Any other value falls back to Latest rather than changing what the endpoint means.",
            "schema": {
              "type": "string",
              "description": "Search ordering: Latest (default, reverse-chronological) or Top (X's ranked ordering, materially slower upstream). Any other value falls back to Latest rather than changing what the endpoint means.",
              "example": "Latest"
            },
            "example": "Latest"
          },
          {
            "name": "strict",
            "in": "query",
            "required": false,
            "description": "Set to true to drop every returned row that does not demonstrably quote the requested tweet, instead of only counting them in quote_matched. Default false, because X does not embed the quoted original on every search result, so strict mode can hide real quotes.",
            "schema": {
              "type": "boolean",
              "description": "Set to true to drop every returned row that does not demonstrably quote the requested tweet, instead of only counting them in quote_matched. Default false, because X does not embed the quoted original on every search result, so strict mode can hide real quotes.",
              "example": "false"
            },
            "example": "false"
          }
        ]
      }
    },
    "/twitter/tweet/thread": {
      "get": {
        "operationId": "tweet-thread",
        "summary": "Tweet Thread",
        "description": "Given the first tweet of a thread, return the ordered list of tweets that make up the author's connected thread. The endpoint reads forward from the tweet you pass and does not walk backwards, so pass the thread's first tweet, which is the conversation_id carried on every tweet in that thread. Passing a later tweet returns only the tail of the thread. Cost: $0.0040 per call.",
        "tags": [
          "Tweet Details"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.004,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/tweet/thread?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/tweet/thread\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/thread\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Reconstruct a thread forward from its first tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Ordered tweets composing the thread.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of tweets in the thread. The whole thread is returned in one call, so there is no cursor and no second page."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "1/ Here is how we made the API 100x cheaper.",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      }
                    },
                    {
                      "id": "1759123456789012346",
                      "text": "2/ It starts with batching ~20 tweets per call.",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      }
                    }
                  ],
                  "next_cursor": ""
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of any tweet in the thread. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of any tweet in the thread. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of any tweet in the thread. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of any tweet in the thread. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          }
        ]
      }
    },
    "/twitter/user/info": {
      "get": {
        "operationId": "user-info",
        "summary": "User Info by Username",
        "description": "Resolve a username into the full user object: bio, follower and following counts, verification status, location, and avatar. The canonical entry point for profile lookups. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/info?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/info\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/info\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a full profile by @handle.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/User"
                        }
                      ],
                      "description": "The resolved user object."
                    }
                  }
                },
                "example": {
                  "user": {
                    "id": "745273",
                    "username": "naval",
                    "name": "Naval",
                    "description": "Angel investor.",
                    "followers_count": 2100000,
                    "following_count": 421,
                    "verified": true,
                    "profile_image_url": "https://pbs.twimg.com/profile_images/.../avatar.jpg"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          }
        ]
      }
    },
    "/twitter/user/info_by_id": {
      "get": {
        "operationId": "user-info-by-id",
        "summary": "User Info by ID",
        "description": "Resolve a numeric user ID into the full user object. Use this when you already have the stable ID (handles can change, IDs do not). Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/info_by_id?user_id=745273\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/info_by_id\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"user_id\": \"745273\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/info_by_id\");\nurl.search = new URLSearchParams({ user_id: \"745273\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a full profile by numeric user ID.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "user": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/User"
                        }
                      ],
                      "description": "The resolved user object."
                    }
                  }
                },
                "example": {
                  "user": {
                    "id": "745273",
                    "username": "naval",
                    "name": "Naval",
                    "followers_count": 2100000,
                    "verified": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the user.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the user.",
              "example": "745273"
            },
            "example": "745273"
          }
        ]
      }
    },
    "/twitter/user/status": {
      "get": {
        "operationId": "user-status",
        "summary": "User Status",
        "description": "Return the liveness state of a handle: alive, suspended, not_found, or unavailable. Every outcome is an HTTP 200 and the caller branches on the status field. This exists because a standard profile lookup collapses suspended, deleted, and never-existed into one indistinguishable 404. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/status?userName=openai\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/status\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"userName\": \"openai\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/status\");\nurl.search = new URLSearchParams({ userName: \"openai\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Check whether an account is alive, suspended, or deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "userName": {
                      "type": "string",
                      "description": "The handle you asked about, echoed back."
                    },
                    "status": {
                      "type": "string",
                      "description": "One of alive, suspended, not_found, or unavailable. `unavailable` means X reported a state we do not map to the other three; the reason field carries its wording."
                    },
                    "id": {
                      "type": "object",
                      "description": "The numeric user ID when the account is alive; null otherwise.",
                      "additionalProperties": true
                    },
                    "reason": {
                      "type": "object",
                      "description": "X's own explanation when it gives one; null for a healthy account.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "userName": "openai",
                  "status": "alive",
                  "id": "1634058197493178368",
                  "reason": null
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "userName",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @. The alias `username` is also accepted.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @. The alias `username` is also accepted.",
              "example": "openai"
            },
            "example": "openai"
          }
        ]
      }
    },
    "/twitter/user/user_about": {
      "get": {
        "operationId": "user-user-about",
        "summary": "User About",
        "description": "Read a profile's full About object: identity, bio, location, linked website, avatar, verification and identity-verification flags, professional account type and categories, follower and following counts, the account creation date, and X's \"About this account\" transparency panel (account country, how the account was created, and username-change history). Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/user_about?username=stripe\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/user_about\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"stripe\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/user_about\");\nurl.search = new URLSearchParams({ username: \"stripe\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a profile's extended About / professional details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "about": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/About"
                        }
                      ],
                      "description": "The profile's full About object: identity, bio, location, linked website, avatar, verification and identity-verification flags, professional account type and categories, follower and following counts, the account creation date, and X's \"About this account\" transparency panel (account country, how the account was created, and username-change history)."
                    }
                  }
                },
                "example": {
                  "about": {
                    "id": "13334762",
                    "username": "stripe",
                    "name": "Stripe",
                    "description": "Payments infrastructure for the internet.",
                    "location": "San Francisco, CA",
                    "url": "https://stripe.com",
                    "is_blue_verified": true,
                    "verified": true,
                    "verified_type": "Business",
                    "professional_type": "Business",
                    "professional_categories": [
                      "Software Company"
                    ],
                    "followers_count": 312000,
                    "following_count": 412,
                    "created_at": "Tue Feb 12 18:02:11 +0000 2008",
                    "profile_image_url": "https://pbs.twimg.com/profile_images/1841086032213626880/example_normal.jpg",
                    "is_identity_verified": false,
                    "verified_since": null,
                    "account_based_in": "United States",
                    "created_via": "United States App Store",
                    "username_changes": {
                      "count": 0,
                      "last_changed_at": null
                    },
                    "created_country_accurate": true,
                    "location_accurate": true,
                    "learn_more_url": "https://help.twitter.com/managing-your-account/about-twitter-verified-accounts"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @. Required: unlike the other user reads, this endpoint cannot be called with user_id alone.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @. Required: unlike the other user reads, this endpoint cannot be called with user_id alone.",
              "example": "stripe"
            },
            "example": "stripe"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID. Not currently a substitute for username on this endpoint: a user_id-only request fails upstream. Resolve the ID to a handle with GET /user/info_by_id and pass username.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID. Not currently a substitute for username on this endpoint: a user_id-only request fails upstream. Resolve the ID to a handle with GET /user/info_by_id and pass username.",
              "example": "44196397"
            },
            "example": "44196397"
          }
        ]
      }
    },
    "/twitter/user/media": {
      "get": {
        "operationId": "user-media",
        "summary": "User Media",
        "description": "Fetch the media tweets posted by a user, cursor-paginated. Returns the tweet objects from the account's Media tab, with media URLs included under extended_entities.media. The tab occasionally surfaces a link-or-card tweet with no attachment, so guard on extended_entities before reading it. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/media?username=nasa\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/media\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"nasa\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/media\");\nurl.search = new URLSearchParams({ username: \"nasa\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through a profile's media tweets (images and video).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Media tweets for this page (each carries its attachments under extended_entities.media).",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1759987654321000111",
                      "text": "A new image of the Pillars of Creation.",
                      "extended_entities": {
                        "media": [
                          {
                            "type": "photo",
                            "media_url_https": "https://pbs.twimg.com/media/abc.jpg",
                            "url": "https://t.co/abc123",
                            "ext_alt_text": "The Pillars of Creation imaged by JWST."
                          }
                        ]
                      },
                      "author": {
                        "id": "11348282",
                        "username": "nasa"
                      }
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "nasa"
            },
            "example": "nasa"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/tweets": {
      "get": {
        "operationId": "user-tweets",
        "summary": "User Tweets",
        "description": "Page through a user's public timeline, cursor-paginated at roughly 20 tweets per call. The page mirrors the account's timeline as X returns it, so it contains original tweets, retweets, and the account's own replies. Each tweet carries is_retweet and is_reply, so filter client-side if you want original posts only. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/tweets?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/tweets\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/tweets\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/tweets?username=naval&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/tweets\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"username\": \"naval\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { username: \"naval\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/tweets\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a user's public timeline (original tweets, retweets, and their own replies).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Timeline tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "Reading > scrolling.",
                      "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      },
                      "favorite_count": 4821
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Accepted but not honoured on this endpoint: the upstream timeline page is fixed at roughly 20 tweets and raising count does not return more. Use cursor to read further back.",
            "schema": {
              "type": "integer",
              "description": "Accepted but not honoured on this endpoint: the upstream timeline page is fixed at roughly 20 tweets and raising count does not return more. Use cursor to read further back.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/tweets_and_replies": {
      "get": {
        "operationId": "user-tweets-and-replies",
        "summary": "User Tweets and Replies",
        "description": "Page through a user's public timeline including the replies the account posted. This endpoint resolves to the same upstream timeline as GET /user/tweets and returns the same tweets in the same order, so treat it as an alias kept for compatibility rather than a wider result set. Each tweet carries is_retweet and is_reply for client-side filtering. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/tweets_and_replies?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/tweets_and_replies\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/tweets_and_replies\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch a user's timeline including their replies (same upstream timeline as User Tweets).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Timeline tweets and replies for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "@founder Great point, here is the data.",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      }
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Accepted but not honoured on this endpoint: the upstream timeline page is fixed at roughly 20 tweets and raising count does not return more. Use cursor to read further back.",
            "schema": {
              "type": "integer",
              "description": "Accepted but not honoured on this endpoint: the upstream timeline page is fixed at roughly 20 tweets and raising count does not return more. Use cursor to read further back.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/mentions": {
      "get": {
        "operationId": "user-mentions",
        "summary": "User Mentions",
        "description": "Return the tweets that mention a given account, cursor-paginated. This is the canonical way to read a handle's mentions; it is a thin wrapper over a to:username search and returns the same tweet objects. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/mentions?username=twitterapis\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/mentions\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"twitterapis\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/mentions\");\nurl.search = new URLSearchParams({ username: \"twitterapis\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch tweets that mention a username.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Tweets mentioning the username, for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1759555444333222111",
                      "text": "@twitterapis just shipped great docs.",
                      "author": {
                        "id": "9921",
                        "username": "devjane"
                      }
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @ to find mentions of.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @ to find mentions of.",
              "example": "twitterapis"
            },
            "example": "twitterapis"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Accepted but not honoured on this endpoint: the upstream page is fixed at roughly 20 results and raising count does not return more. Use cursor to read further.",
            "schema": {
              "type": "integer",
              "description": "Accepted but not honoured on this endpoint: the upstream page is fixed at roughly 20 results and raising count does not return more. Use cursor to read further.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/affiliates": {
      "get": {
        "operationId": "user-affiliates",
        "summary": "User Affiliates",
        "description": "Return the affiliated accounts linked under an organization's Verified Organizations profile. Useful for mapping a company to its employees and brand accounts. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/affiliates?username=stripe\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/affiliates\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"stripe\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/affiliates\");\nurl.search = new URLSearchParams({ username: \"stripe\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List the affiliated sub-accounts of an organization profile.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Affiliated user accounts for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "12345",
                      "username": "stripedev",
                      "name": "Stripe Developers",
                      "verified": true
                    }
                  ],
                  "next_cursor": ""
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle of the organization account.",
            "schema": {
              "type": "string",
              "description": "Handle of the organization account.",
              "example": "stripe"
            },
            "example": "stripe"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "team",
            "in": "query",
            "required": false,
            "description": "Affiliate team filter, when the organization exposes teams.",
            "schema": {
              "type": "string",
              "description": "Affiliate team filter, when the organization exposes teams."
            }
          }
        ]
      }
    },
    "/twitter/user/check_follow_relationship": {
      "get": {
        "operationId": "user-check-follow-relationship",
        "summary": "Check Follow Relationship",
        "description": "Return the directional relationship between a source and target user: whether source follows target (following) and target follows source (followed_by), plus block, mute, and DM-eligibility flags. The relationship object is null when either user is not found. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/check_follow_relationship?source_user_id=745273&target_user_id=2178758961\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/check_follow_relationship\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"source_user_id\": \"745273\", \"target_user_id\": \"2178758961\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/check_follow_relationship\");\nurl.search = new URLSearchParams({ source_user_id: \"745273\", target_user_id: \"2178758961\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Check whether one user follows another.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "relationship": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Relationship"
                        }
                      ],
                      "description": "The directional relationship between source and target. Null when either user is not found."
                    }
                  }
                },
                "example": {
                  "relationship": {
                    "source_id": "745273",
                    "target_id": "2178758961",
                    "following": true,
                    "followed_by": false,
                    "blocking": null,
                    "blocked_by": null,
                    "muting": null,
                    "can_dm": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "source_user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the account whose following is checked.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the account whose following is checked.",
              "example": "745273"
            },
            "example": "745273"
          },
          {
            "name": "target_user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the account being checked against.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the account being checked against.",
              "example": "2178758961"
            },
            "example": "2178758961"
          }
        ]
      }
    },
    "/twitter/user/bookmarks": {
      "get": {
        "operationId": "user-bookmarks",
        "summary": "Bookmarks",
        "description": "Fetch the bookmarked tweets for the account behind your registered session, newest first. Each item is a full tweet object with author and engagement counts. Cursor-paginated. Requires a registered session. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/bookmarks?count=20\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/bookmarks\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"count\": 20},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmarks\");\nurl.search = new URLSearchParams({ count: \"20\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/bookmarks?cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/bookmarks\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmarks\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "List your registered account's bookmarked tweets, most recent first.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Bookmarked tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "DAACCgAC...",
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "Bookmark this thread on cursor pagination.",
                      "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                      "author": {
                        "id": "745273",
                        "username": "naval",
                        "name": "Naval"
                      },
                      "favorite_count": 4821,
                      "retweet_count": 612,
                      "view_count": 219340
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/bookmark_search": {
      "get": {
        "operationId": "user-bookmark-search",
        "summary": "Bookmark Search",
        "description": "Search the bookmarks of the account behind your registered session by keyword. Matches against bookmarked tweet text and returns full tweet objects. Cursor-paginated. Requires a registered session. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/bookmark_search?query=cursor%20pagination\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/bookmark_search\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"query\": \"cursor pagination\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmark_search\");\nurl.search = new URLSearchParams({ query: \"cursor pagination\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/bookmark_search?query=cursor&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/bookmark_search\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"query\": \"cursor\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { query: \"cursor\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmark_search\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Full-text search within your registered account's bookmarks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Matching bookmarked tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "DAACCgAC...",
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "The empty array is the universal stop signal for cursor pagination.",
                      "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                      "author": {
                        "id": "745273",
                        "username": "naval",
                        "name": "Naval"
                      },
                      "favorite_count": 4821
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "Keyword(s) to match against your bookmarked tweets' text.",
            "schema": {
              "type": "string",
              "description": "Keyword(s) to match against your bookmarked tweets' text.",
              "example": "cursor pagination"
            },
            "example": "cursor pagination"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/bookmark_folders": {
      "get": {
        "operationId": "user-bookmark-folders",
        "summary": "Bookmark Folders",
        "description": "Fetch the caller's own bookmark folders. Each item carries the folder's id, name, and a cover image X auto-picks from its contents. Requires a registered session. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/bookmark_folders\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/bookmark_folders\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmark_folders\");\nurl.search = new URLSearchParams({}).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List your registered account's bookmark folders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of folders returned."
                    },
                    "folders": {
                      "type": "array",
                      "description": "The caller's own bookmark folders: id, name, cover_media_url.",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "folders": [
                    {
                      "id": "2073826456430592429",
                      "name": "Parasite SEO",
                      "cover_media_url": "https://pbs.twimg.com/media/Ex_fuubVEAA9gcg.png"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/user/bookmark_folder_timeline": {
      "get": {
        "operationId": "user-bookmark-folder-timeline",
        "summary": "Bookmark Folder Timeline",
        "description": "Fetch the tweets inside one of the caller's own bookmark folders, identified by folder_id (from Bookmark Folders). Cursor-paginated. Requires a registered session. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline?folder_id=2073826456430592429\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"folder_id\": \"2073826456430592429\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline\");\nurl.search = new URLSearchParams({ folder_id: \"2073826456430592429\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline?folder_id=2073826456430592429&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"folder_id\": \"2073826456430592429\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { folder_id: \"2073826456430592429\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/bookmark_folder_timeline\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Read the tweets inside one of your bookmark folders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "folder_id": {
                      "type": "string",
                      "description": "Echo of the folder_id you queried."
                    },
                    "tweets": {
                      "type": "array",
                      "description": "Tweets saved inside this folder, for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "folder_id": "2073826456430592429",
                  "count": 1,
                  "next_cursor": "-1783273732069",
                  "tweets": [
                    {
                      "id": "2073438646657564825",
                      "text": "https://t.co/dYukCmrM45",
                      "created_at": "Sat Jul 04 16:07:50 +0000 2026",
                      "author": {
                        "id": "1451118635108478976",
                        "username": "natiakourdadze",
                        "name": "Natia Kurdadze"
                      },
                      "favorite_count": 41,
                      "retweet_count": 5,
                      "view_count": 6332
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "folder_id",
            "in": "query",
            "required": true,
            "description": "The bookmark folder's id, from user/bookmark_folders.",
            "schema": {
              "type": "string",
              "description": "The bookmark folder's id, from user/bookmark_folders.",
              "example": "2073826456430592429"
            },
            "example": "2073826456430592429"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/likes": {
      "get": {
        "operationId": "user-likes",
        "summary": "User Likes",
        "description": "Read the Likes tab of the account named by user_id, read through your registered session, most recent first. Returns full tweet objects, cursor-paginated. Returns an empty list when the account hides its likes. Requires a registered session and a numeric user_id. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/likes?user_id=44196397\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/likes\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"user_id\": \"44196397\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/likes\");\nurl.search = new URLSearchParams({ user_id: \"44196397\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/likes?user_id=44196397&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/likes\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"user_id\": \"44196397\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { user_id: \"44196397\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/likes\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch the tweets a target account has liked (its public Likes tab).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Liked tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "DAACCgAC...",
                  "tweets": [
                    {
                      "id": "1759123456789012345",
                      "text": "A tweet this account liked.",
                      "created_at": "Tue Feb 20 14:02:11 +0000 2026",
                      "author": {
                        "id": "745273",
                        "username": "naval",
                        "name": "Naval"
                      },
                      "favorite_count": 4821
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the account whose likes to read. Resolve a handle with GET /user/info first.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the account whose likes to read. Resolve a handle with GET /user/info first.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/home_timeline": {
      "get": {
        "operationId": "user-home-timeline",
        "summary": "Home Timeline",
        "description": "Read the home timeline for the account behind your registered session: the ranked feed shown when that account opens X, most recent first. Returns full tweet objects with author and engagement counts. Cursor-paginated. Requires a registered session. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/home_timeline?count=20\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/home_timeline\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"count\": 20},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/home_timeline\");\nurl.search = new URLSearchParams({ count: \"20\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/home_timeline?cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/home_timeline\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/home_timeline\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Fetch your registered account's home timeline (the For You / Following feed).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Timeline tweets for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "DAABCgABHL4VFSR__9oKAAIA...",
                  "tweets": [
                    {
                      "id": "2070410316496678962",
                      "text": "Bitcoin closed the daily candle above the key support.",
                      "created_at": "Fri Jun 26 07:34:20 +0000 2026",
                      "lang": "en",
                      "author": {
                        "id": "3185716686",
                        "username": "AshCrypto",
                        "name": "Ash Crypto",
                        "verified": true,
                        "followers_count": 2168823
                      },
                      "reply_count": 264,
                      "retweet_count": 309,
                      "favorite_count": 1277,
                      "quote_count": 11,
                      "bookmark_count": 24,
                      "view_count": 130944
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/blocking": {
      "get": {
        "operationId": "user-blocking",
        "summary": "Blocked Accounts",
        "description": "Return the accounts blocked by the account behind your registered session, as full user objects, cursor-paginated. This reads your OWN block list. There is no user_id parameter because X exposes no way to read another account's blocks, so the endpoint does not pretend to offer one. Requires a registered session or per-call inline credentials. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/blocking?count=20\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/blocking\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"count\": 20},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/blocking\");\nurl.search = new URLSearchParams({ count: \"20\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/blocking?cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.users | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.users[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/blocking\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"users\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/blocking\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.users ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "List the accounts your registered account has blocked.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Accounts you have blocked, for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "1353384573435056128|2071116068906074107",
                  "users": [
                    {
                      "id": "1353384573435056128",
                      "username": "cryptorover",
                      "name": "Crypto Rover",
                      "verified": true,
                      "followers_count": 812443,
                      "description": "Daily crypto analysis.",
                      "created_at": "Sun Jan 24 16:50:08 +0000 2021",
                      "profile_image_url": "https://pbs.twimg.com/profile_images/1891433835675475969/J-TloTb6_normal.png"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/muting": {
      "get": {
        "operationId": "user-muting",
        "summary": "Muted Accounts",
        "description": "Return the accounts muted by the account behind your registered session, as full user objects, cursor-paginated. Muting hides someone's posts from your timeline without blocking them, so this list is distinct from GET /user/blocking. This reads your OWN mute list; X exposes no way to read another account's, so there is no user_id parameter. Requires a registered session or per-call inline credentials. Cost: $0.0008 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/muting?count=20\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/muting\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"count\": 20},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/muting\");\nurl.search = new URLSearchParams({ count: \"20\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/muting?cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.users | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.users[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/muting\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"users\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/muting\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.users ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "List the accounts your registered account has muted.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Accounts you have muted, for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "1353384573435056128|2071116068906074107",
                  "users": [
                    {
                      "id": "1353384573435056128",
                      "username": "cryptorover",
                      "name": "Crypto Rover",
                      "verified": true,
                      "followers_count": 812443,
                      "description": "Daily crypto analysis.",
                      "created_at": "Sun Jan 24 16:50:08 +0000 2021",
                      "profile_image_url": "https://pbs.twimg.com/profile_images/1891433835675475969/J-TloTb6_normal.png"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/tweets/complete": {
      "get": {
        "operationId": "user-tweets-complete",
        "summary": "Full Tweet History",
        "description": "Collect a user's tweet history in bulk, auto-paginating server-side across upstream pages. Unlike GET /user/tweets (one upstream page per call), this drives pagination for you and returns a large batch in one request. Each call is bounded by both `max` and a server-side time budget, so it always returns inside a normal client timeout. When more history remains the response carries a `next_cursor` — pass it back as `cursor` to continue, and repeat until `next_cursor` is null. Uses the public account pool: no registered session required. Cost: $0.0024 per call.",
        "tags": [
          "User Reads"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0024,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/tweets/complete?user_id=44196397&max=200\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/tweets/complete\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"user_id\": \"44196397\", \"max\": 200},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/tweets/complete\");\nurl.search = new URLSearchParams({ user_id: \"44196397\", max: \"200\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Auto-paginate a large batch of a user's tweet history per call, resuming with a cursor up to Twitter's ~3200 ceiling.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of tweets returned in the flat array."
                    },
                    "next_cursor": {
                      "type": "object",
                      "description": "Non-null means MORE HISTORY REMAINS and this call was truncated (by max, or by the server-side time budget): call again with cursor set to this value. Null means the history is genuinely exhausted. A client that ignores this field will silently receive only part of the history.",
                      "additionalProperties": true
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when more history remains: this page returned tweets and next_cursor is non-null. False once the history is exhausted. Equivalent to testing next_cursor, provided as a convenience loop-stop flag."
                    },
                    "tweets": {
                      "type": "array",
                      "description": "The collected tweets, newest first. Includes retweets (is_retweet true).",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    }
                  }
                },
                "example": {
                  "count": 201,
                  "next_cursor": "DAAHCgABHNqVL6L__zsLAAIAAAAT",
                  "tweets": [
                    {
                      "id": "2071092912000246106",
                      "text": "RT @XFreeze: xAI models now support Zero Data Retention (ZDR) on OpenRouter",
                      "created_at": "Sun Jun 28 04:46:43 +0000 2026",
                      "lang": "en",
                      "is_retweet": true,
                      "is_quote": false,
                      "author": {
                        "id": "44196397",
                        "username": "elonmusk",
                        "name": "Elon Musk",
                        "verified": true,
                        "followers_count": 240574388
                      },
                      "retweet_count": 208,
                      "view_count": 599857
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the target account. Resolve a handle with GET /user/info first.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the target account. Resolve a handle with GET /user/info first.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "max",
            "in": "query",
            "required": false,
            "description": "Target number of tweets to collect in this call. Defaults to 200. This is a MINIMUM target, not a hard cap: pages arrive in whole chunks, so a response may contain up to one page (<=100) more than requested. Twitter's ~3200-per-user history ceiling still applies overall.",
            "schema": {
              "type": "integer",
              "description": "Target number of tweets to collect in this call. Defaults to 200. This is a MINIMUM target, not a hard cap: pages arrive in whole chunks, so a response may contain up to one page (<=100) more than requested. Twitter's ~3200-per-user history ceiling still applies overall.",
              "example": "200"
            },
            "example": "200"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Resume point from a previous response's next_cursor. Omit on the first call. Pass it back to continue collecting where the last call stopped.",
            "schema": {
              "type": "string",
              "description": "Resume point from a previous response's next_cursor. Omit on the first call. Pass it back to continue collecting where the last call stopped.",
              "example": "DAAHCgABHNqVL6L__zs"
            },
            "example": "DAAHCgABHNqVL6L__zs"
          }
        ]
      }
    },
    "/twitter/dm/send": {
      "post": {
        "operationId": "dm-send",
        "summary": "Send DM",
        "description": "Send a direct message to a user as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Direct Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/dm/send\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{recipient_id=44196397&text=Hello%20from%20the%20TwitterAPIs%20DM%20API}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/dm/send\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"recipient_id\": \"44196397\", \"text\": \"Hello from the TwitterAPIs DM API\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/dm/send\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ recipient_id: \"44196397\", text: \"Hello from the TwitterAPIs DM API\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Send a direct message from your authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the message was sent."
                    },
                    "message_id": {
                      "type": "string",
                      "description": "ID of the sent message, or null if it failed."
                    },
                    "conversation_id": {
                      "type": "string",
                      "description": "ID of the conversation the message landed in, or null if the upstream response did not include it."
                    },
                    "recipient_id": {
                      "type": "string",
                      "description": "The recipient's numeric user ID."
                    },
                    "text": {
                      "type": "string",
                      "description": "The message body that was sent."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "message_id": "1899999999999999999",
                  "conversation_id": "44196397-11348282",
                  "recipient_id": "44196397",
                  "text": "Hello from the TwitterAPIs DM API"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipient_id": {
                    "type": "string",
                    "description": "Numeric Twitter user ID of the recipient.",
                    "example": "44196397"
                  },
                  "text": {
                    "type": "string",
                    "description": "The message body. Also accepted in a JSON request body.",
                    "example": "Hello from the TwitterAPIs DM API"
                  }
                },
                "required": [
                  "recipient_id",
                  "text"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/dm/list": {
      "get": {
        "operationId": "dm-list",
        "summary": "DM Inbox",
        "description": "List the DM conversations (inbox) for the account behind your session. Returns each conversation's ID, type, and participant user IDs. Pass a conversation_id to GET /dm/conversation to read its messages. Authenticate with a registered session (POST /customer/session) or per-call x-auth-token and x-ct0 headers, so one API key can poll the inboxes of many accounts. Read-only: this does not send DMs. Cost: $0.0016 per call.",
        "tags": [
          "Direct Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/dm/list\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/dm/list\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/dm/list\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List the Direct Message conversations for your registered account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of conversations returned."
                    },
                    "conversations": {
                      "type": "array",
                      "description": "Conversation entries, each with conversation_id, type (for example ONE_TO_ONE or GROUP_DM, may be null), and participants (numeric user-ID strings).",
                      "items": {
                        "$ref": "#/components/schemas/DMConversation"
                      }
                    }
                  }
                },
                "example": {
                  "count": 2,
                  "conversations": [
                    {
                      "conversation_id": "1749154312754794496-1972455697997824000",
                      "type": "ONE_TO_ONE",
                      "participants": [
                        "1749154312754794496",
                        "1972455697997824000"
                      ]
                    },
                    {
                      "conversation_id": "1796873533852692480-1972455697997824000",
                      "type": "ONE_TO_ONE",
                      "participants": [
                        "1796873533852692480",
                        "1972455697997824000"
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/dm/conversation": {
      "get": {
        "operationId": "dm-conversation",
        "summary": "DM Conversation",
        "description": "Fetch the messages inside a single DM conversation. Pass a conversation_id from GET /dm/list. Each message carries its ID, sender ID, timestamp, and text. Authenticate with a registered session (POST /customer/session) or per-call x-auth-token and x-ct0 headers. Read-only: this does not send DMs. Cost: $0.0016 per call.",
        "tags": [
          "Direct Messages"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/dm/conversation?conversation_id=1749154312754794496-1972455697997824000\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/dm/conversation\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"conversation_id\": \"1749154312754794496-1972455697997824000\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/dm/conversation\");\nurl.search = new URLSearchParams({ conversation_id: \"1749154312754794496-1972455697997824000\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Read the message history of one DM conversation by conversation_id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "conversation_id": {
                      "type": "string",
                      "description": "Echo of the conversation_id you requested."
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of messages returned."
                    },
                    "messages": {
                      "type": "array",
                      "description": "Messages, each with id, time (epoch milliseconds as a string, or null), sender_id (numeric user-ID string, or null), and text.",
                      "items": {
                        "$ref": "#/components/schemas/DMMessage"
                      }
                    }
                  }
                },
                "example": {
                  "conversation_id": "1749154312754794496-1972455697997824000",
                  "count": 1,
                  "messages": [
                    {
                      "id": "1988752174906749349",
                      "time": "1762990442000",
                      "sender_id": "1972455697997824000",
                      "text": "This isnt my main, chat to me here @baywilliams_12"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "conversation_id",
            "in": "query",
            "required": true,
            "description": "Conversation ID from a GET /dm/list entry.",
            "schema": {
              "type": "string",
              "description": "Conversation ID from a GET /dm/list entry.",
              "example": "1749154312754794496-1972455697997824000"
            },
            "example": "1749154312754794496-1972455697997824000"
          }
        ]
      }
    },
    "/twitter/user/followers_you_know": {
      "get": {
        "operationId": "user-followers-you-know",
        "summary": "Followers You Know",
        "description": "Return the followers of the account named by user_id that the account behind your registered session also follows: the mutual-connection overlap from your perspective. Returns full user objects, cursor-paginated. Requires a registered session and a numeric user_id. Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/followers_you_know?user_id=44196397\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/followers_you_know\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"user_id\": \"44196397\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/followers_you_know\");\nurl.search = new URLSearchParams({ user_id: \"44196397\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/followers_you_know?user_id=44196397&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.users | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.users[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/followers_you_know\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"user_id\": \"44196397\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"users\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { user_id: \"44196397\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/followers_you_know\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.users ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "The followers of a target account that your registered account also follows (mutual overlap).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Overlap accounts (followers of the target that you also follow) for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": "1353384573435056128|2071116068906074107",
                  "users": [
                    {
                      "id": "1353384573435056128",
                      "username": "cryptorover",
                      "name": "Crypto Rover",
                      "description": "#Bitcoin Crypto YouTuber",
                      "followers_count": 1596989,
                      "following_count": 555,
                      "verified": true,
                      "tweet_count": 70185,
                      "location": "Bitcoin",
                      "created_at": "Sun Jan 24 16:50:08 +0000 2021",
                      "profile_image_url": "https://pbs.twimg.com/profile_images/1891433835675475969/J-TloTb6_normal.png"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the target account to compute shared followers against.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the target account to compute shared followers against.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; documented cap 100. NOTE: X returns this list in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint, not an exact limit; paginate with the cursor for more.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; documented cap 100. NOTE: X returns this list in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint, not an exact limit; paginate with the cursor for more."
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/user/followers": {
      "get": {
        "operationId": "user-followers",
        "summary": "User Followers",
        "description": "Fetch a user's followers, cursor-paginated. Returns full user objects. For large accounts, page with next_cursor until the users array comes back empty (the follower graph keeps returning a non-null cursor even on the final page). Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/followers?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/followers\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/followers\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/user/followers?username=naval&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.users | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.users[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/user/followers\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"username\": \"naval\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"users\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { username: \"naval\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/user/followers\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.users ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the accounts that follow a user.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Follower user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "9921",
                      "username": "devjane",
                      "name": "Jane",
                      "followers_count": 4200,
                      "verified": false
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/following": {
      "get": {
        "operationId": "user-following",
        "summary": "User Following",
        "description": "Fetch the accounts a user follows, cursor-paginated. Returns full user objects. Page with next_cursor until the users array comes back empty (the follower graph keeps returning a non-null cursor even on the final page). Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/following?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/following\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/following\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the accounts a user follows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Followed user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "2178758961",
                      "username": "balajis",
                      "name": "Balaji",
                      "followers_count": 1000000,
                      "verified": true
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/followers_v2": {
      "get": {
        "operationId": "user-followers-v2",
        "summary": "User Followers (v2)",
        "description": "The v2 variant of the followers endpoint. Same data, with a more consistent cursor model and additional user fields. Prefer v2 for new integrations. Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/followers_v2?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/followers_v2\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/followers_v2\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Followers endpoint with the v2 response shape and richer cursoring.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Follower user objects (v2 shape) for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "9921",
                      "username": "devjane",
                      "name": "Jane",
                      "followers_count": 4200,
                      "verified": false,
                      "created_at": "Wed Jan 04 09:11:00 +0000 2023"
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/following_v2": {
      "get": {
        "operationId": "user-following-v2",
        "summary": "User Following (v2)",
        "description": "The v2 variant of the following endpoint. Same data as the v1 following call, with a more consistent cursor model and additional user fields. Prefer v2 for new integrations. Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/following_v2?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/following_v2\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/following_v2\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Following endpoint with the v2 response shape and richer cursoring.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Followed user objects (v2 shape) for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "2178758961",
                      "username": "balajis",
                      "name": "Balaji",
                      "followers_count": 1000000,
                      "verified": true,
                      "created_at": "Fri Nov 08 04:22:10 +0000 2013"
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; documented range 1-100. NOTE: on follower/following lists X returns pages in fixed chunks, so a small count may still return up to a full page (~100). Treat count as an upper-bound hint here, not an exact limit; paginate with the cursor for more.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/user/verified_followers": {
      "get": {
        "operationId": "user-verified-followers",
        "summary": "Verified Followers",
        "description": "Fetch only the Verified (Blue) accounts that follow a user, cursor-paginated. A fast way to filter a large follower base down to higher-signal accounts. Cost: $0.0008 per call.",
        "tags": [
          "Follower Graph"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/user/verified_followers?username=naval\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/user/verified_followers\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"username\": \"naval\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/verified_followers\");\nurl.search = new URLSearchParams({ username: \"naval\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through only the verified accounts that follow a user.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Verified follower user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "2178758961",
                      "username": "balajis",
                      "name": "Balaji",
                      "verified": true,
                      "followers_count": 1000000
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "username",
            "in": "query",
            "required": true,
            "description": "Handle without the leading @.",
            "schema": {
              "type": "string",
              "description": "Handle without the leading @.",
              "example": "naval"
            },
            "example": "naval"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "Numeric user ID; provide either username or user_id.",
            "schema": {
              "type": "string",
              "description": "Numeric user ID; provide either username or user_id.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/list/members": {
      "get": {
        "operationId": "list-members",
        "summary": "List Members",
        "description": "Fetch the members of a public List by its numeric ID, cursor-paginated. Returns full user objects for every account in the List. Cost: $0.0008 per call.",
        "tags": [
          "List Data"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/list/members?list_id=1234567890123456789\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/list/members\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"list_id\": \"1234567890123456789\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/list/members\");\nurl.search = new URLSearchParams({ list_id: \"1234567890123456789\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the members of a public Twitter/X List.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "List member user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "745273",
                      "username": "naval",
                      "name": "Naval",
                      "verified": true
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "list_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the public List.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the public List.",
              "example": "1234567890123456789"
            },
            "example": "1234567890123456789"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/list/followers": {
      "get": {
        "operationId": "list-followers",
        "summary": "List Followers",
        "description": "Fetch a public List's followers by its numeric ID, cursor-paginated. Followers and members are different sets of people: members are the accounts the List owner added to it, followers are the accounts that subscribed to read it. A List with hundreds of members commonly has only a handful of followers, so a small count here is normal and is not a truncated page. next_cursor is null once X marks the roster complete. Cost: $0.0008 per call.",
        "tags": [
          "List Data"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/list/followers?list_id=1234567890123456789\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/list/followers\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"list_id\": \"1234567890123456789\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/list/followers\");\nurl.search = new URLSearchParams({ list_id: \"1234567890123456789\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through the accounts that follow a public Twitter/X List.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "users": {
                      "type": "array",
                      "description": "Follower user objects for this page.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "users": [
                    {
                      "id": "745273",
                      "username": "naval",
                      "name": "Naval",
                      "verified": true
                    }
                  ],
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "list_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the public List.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the public List.",
              "example": "1234567890123456789"
            },
            "example": "1234567890123456789"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/list/tweets": {
      "get": {
        "operationId": "list-tweets",
        "summary": "List Tweets",
        "description": "Fetch posts written by the members of a public List through X's search index. Supports since and until date bounds and an include_replies toggle. Does not include retweets. Cost: $0.0008 per call.",
        "tags": [
          "List Data"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/list/tweets?list_id=1234567890123456789&since=2026-08-01\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/list/tweets\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"list_id\": \"1234567890123456789\", \"since\": \"2026-08-01\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/list/tweets\");\nurl.search = new URLSearchParams({ list_id: \"1234567890123456789\", since: \"2026-08-01\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Read a public List's posts, filterable by date range and replies.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Posts from this List's members for this page, newest first.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1899887766554433221",
                      "text": "Shipping the thing we said we would ship.",
                      "created_at": "2026-08-14T09:12:44.000Z",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      }
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "list_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the public List.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the public List.",
              "example": "1234567890123456789"
            },
            "example": "1234567890123456789"
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "description": "Only posts on or after this date, as YYYY-MM-DD.",
            "schema": {
              "type": "string",
              "description": "Only posts on or after this date, as YYYY-MM-DD.",
              "example": "2026-08-01"
            },
            "example": "2026-08-01"
          },
          {
            "name": "until",
            "in": "query",
            "required": false,
            "description": "Only posts before this date, as YYYY-MM-DD. Exclusive, matching X's until: operator.",
            "schema": {
              "type": "string",
              "description": "Only posts before this date, as YYYY-MM-DD. Exclusive, matching X's until: operator.",
              "example": "2026-08-15"
            },
            "example": "2026-08-15"
          },
          {
            "name": "include_replies",
            "in": "query",
            "required": false,
            "description": "Whether to include replies written by List members. Default true.",
            "schema": {
              "type": "boolean",
              "description": "Whether to include replies written by List members. Default true.",
              "example": "false"
            },
            "example": "false"
          },
          {
            "name": "product",
            "in": "query",
            "required": false,
            "description": "Which search ranking to read: Latest or Top. Default Latest, and any unrecognised value falls back to Latest.",
            "schema": {
              "type": "string",
              "description": "Which search ranking to read: Latest or Top. Default Latest, and any unrecognised value falls back to Latest.",
              "example": "Top"
            },
            "example": "Top"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          }
        ]
      }
    },
    "/twitter/list/timeline": {
      "get": {
        "operationId": "list-timeline",
        "summary": "List Timeline",
        "description": "Fetch a public List's feed as X itself serves it, using the native List timeline. Includes members' retweets and X's own ordering. Paged only, with no date or reply filters. Cost: $0.0008 per call.",
        "tags": [
          "List Data"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/list/timeline?list_id=1234567890123456789\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/list/timeline\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"list_id\": \"1234567890123456789\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/list/timeline\");\nurl.search = new URLSearchParams({ list_id: \"1234567890123456789\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Read a public List's native X timeline, retweets included.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tweets": {
                      "type": "array",
                      "description": "Posts from X's native List timeline for this page.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of items returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page is available: this page returned items and carried a usable next_cursor. False on the final page. Follower-graph endpoints keep sending a non-null next_cursor past the end, but has_more still flips to false once the item array comes back empty, so it is the reliable loop-stop signal."
                    }
                  }
                },
                "example": {
                  "tweets": [
                    {
                      "id": "1899887766554433222",
                      "text": "Reposting this because it deserves a second look.",
                      "created_at": "2026-08-14T10:03:19.000Z",
                      "author": {
                        "id": "745273",
                        "username": "naval"
                      }
                    }
                  ],
                  "next_cursor": "DAABCgABF..."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "list_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the public List.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the public List.",
              "example": "1234567890123456789"
            },
            "example": "1234567890123456789"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Max items to return for this page. Default 20; clamped to 1-100.",
            "schema": {
              "type": "integer",
              "description": "Max items to return for this page. Default 20; clamped to 1-100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response."
            }
          }
        ]
      }
    },
    "/twitter/trends": {
      "get": {
        "operationId": "trends",
        "summary": "Trends",
        "description": "Fetch the current top trends for one location. Ask for it by country name, ISO code, or numeric WOEID; with no location parameter you get Worldwide. X returns roughly 50 trends per location, ranked. Cost: $0.0008 per call.",
        "tags": [
          "Trends"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/trends?country=US\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/trends\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"country\": \"US\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/trends\");\nurl.search = new URLSearchParams({ country: \"US\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Read the current trending topics for a location.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "location": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/TrendServedLocation"
                        }
                      ],
                      "description": "The location X actually served, as { name, woeid }, echoed back so you know what you got."
                    },
                    "as_of": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of when X computed this trend list."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "ISO 8601 timestamp X reports for the trend window."
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of trends in this response, after any count truncation."
                    },
                    "trends": {
                      "type": "array",
                      "description": "Ranked trend objects: name, url, query, promoted_content, tweet_volume, is_hashtag, rank.",
                      "items": {
                        "$ref": "#/components/schemas/Trend"
                      }
                    }
                  }
                },
                "example": {
                  "location": {
                    "name": "United States",
                    "woeid": 23424977
                  },
                  "as_of": "2026-07-20T06:15:13Z",
                  "created_at": "2026-07-18T15:25:54Z",
                  "count": 2,
                  "trends": [
                    {
                      "name": "Spain",
                      "url": "http://twitter.com/search?q=Spain",
                      "query": "Spain",
                      "promoted_content": null,
                      "tweet_volume": null,
                      "is_hashtag": false,
                      "rank": 1
                    },
                    {
                      "name": "#HOTD",
                      "url": "http://twitter.com/search?q=%23HOTD",
                      "query": "%23HOTD",
                      "promoted_content": null,
                      "tweet_volume": null,
                      "is_hashtag": true,
                      "rank": 2
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Country name or ISO code, e.g. \"US\" or \"Japan\". Resolved against the trends locations list, country-level entries only.",
            "schema": {
              "type": "string",
              "description": "Country name or ISO code, e.g. \"US\" or \"Japan\". Resolved against the trends locations list, country-level entries only.",
              "example": "US"
            },
            "example": "US"
          },
          {
            "name": "woeid",
            "in": "query",
            "required": false,
            "description": "Numeric WOEID from /twitter/trends/locations. Takes precedence over country when both are sent.",
            "schema": {
              "type": "integer",
              "description": "Numeric WOEID from /twitter/trends/locations. Takes precedence over country when both are sent.",
              "example": "23424977"
            },
            "example": "23424977"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Truncate the returned list to this many trends. X has no count of its own; it always returns its full set (about 50).",
            "schema": {
              "type": "integer",
              "description": "Truncate the returned list to this many trends. X has no count of its own; it always returns its full set (about 50).",
              "example": "10"
            },
            "example": "10"
          }
        ]
      }
    },
    "/twitter/trends/locations": {
      "get": {
        "operationId": "trends-locations",
        "summary": "Trend Locations",
        "description": "Fetch the full set of locations X serves trends for, each with the WOEID to pass back to the Trends endpoint. Takes no parameters and returns the complete list. Cost: $0.0008 per call.",
        "tags": [
          "Trends"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/trends/locations\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/trends/locations\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/trends/locations\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List every location Twitter/X has trends available for.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of locations returned."
                    },
                    "locations": {
                      "type": "array",
                      "description": "Location objects: name, woeid, country, country_code, parentid, place_type, url. The deprecated camelCase countryCode/placeType are still returned alongside for a migration window; prefer the snake_case country_code/place_type.",
                      "items": {
                        "$ref": "#/components/schemas/TrendLocation"
                      }
                    }
                  }
                },
                "example": {
                  "count": 467,
                  "locations": [
                    {
                      "name": "Worldwide",
                      "woeid": 1,
                      "country": "",
                      "country_code": null,
                      "countryCode": null,
                      "parentid": 0,
                      "place_type": {
                        "code": 19,
                        "name": "Supername"
                      },
                      "placeType": {
                        "code": 19,
                        "name": "Supername"
                      },
                      "url": "http://where.yahooapis.com/v1/place/1"
                    },
                    {
                      "name": "United States",
                      "woeid": 23424977,
                      "country": "United States",
                      "country_code": "US",
                      "countryCode": "US",
                      "parentid": 1,
                      "place_type": {
                        "code": 12,
                        "name": "Country"
                      },
                      "placeType": {
                        "code": 12,
                        "name": "Country"
                      },
                      "url": "http://where.yahooapis.com/v1/place/23424977"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/spaces/info": {
      "get": {
        "operationId": "spaces-info",
        "summary": "Space Info",
        "description": "Look up a single X Space by its id and get back its title, lifecycle state, host, topics, timing, audience counts and its admin, speaker and listener roster. Works for a Space that is scheduled, running or already ended. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Spaces"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/spaces/info?id=1RKZzjkoYRAKB\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/spaces/info\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1RKZzjkoYRAKB\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/spaces/info\");\nurl.search = new URLSearchParams({ id: \"1RKZzjkoYRAKB\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata and participant roster for one X Space, live or ended.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "space": {
                      "type": "object",
                      "description": "The Space, or null with a 404 when the id resolves to nothing.",
                      "additionalProperties": true
                    },
                    "space.id": {
                      "type": "string",
                      "description": "The Space id, echoed back."
                    },
                    "space.title": {
                      "type": "string",
                      "description": "The Space title as set by the host."
                    },
                    "space.state": {
                      "type": "string",
                      "description": "X's lifecycle value: Scheduled, NotStarted, Running or Ended."
                    },
                    "space.content_type": {
                      "type": "string",
                      "description": "audio for an audio-only Space, visual_audio when the host enabled video."
                    },
                    "space.media_key": {
                      "type": "string",
                      "description": "X's internal media key for the Space recording."
                    },
                    "space.created_at": {
                      "type": "object",
                      "description": "Millisecond epoch. Every timestamp on this object is a number, including ended_at, which X itself sends as a string.",
                      "additionalProperties": true
                    },
                    "space.scheduled_start": {
                      "type": "object",
                      "description": "Millisecond epoch the host scheduled the Space to begin. 0 when absent.",
                      "additionalProperties": true
                    },
                    "space.started_at": {
                      "type": "object",
                      "description": "Millisecond epoch the Space actually began. 0 when it has not started.",
                      "additionalProperties": true
                    },
                    "space.ended_at": {
                      "type": "object",
                      "description": "Millisecond epoch the Space ended. 0 while it is still running.",
                      "additionalProperties": true
                    },
                    "space.total_live_listeners": {
                      "type": "object",
                      "description": "Peak concurrent listeners while the Space was live.",
                      "additionalProperties": true
                    },
                    "space.total_replay_watched": {
                      "type": "object",
                      "description": "Cumulative replay views after the Space ended.",
                      "additionalProperties": true
                    },
                    "space.is_space_available_for_replay": {
                      "type": "boolean",
                      "description": "Whether a replay is available."
                    },
                    "space.is_space_available_for_clipping": {
                      "type": "boolean",
                      "description": "Whether clipping is permitted."
                    },
                    "space.topics": {
                      "type": "object",
                      "description": "Topics the host tagged, each { topic_id, name }.",
                      "additionalProperties": true
                    },
                    "space.creator": {
                      "type": "object",
                      "description": "The host's full user profile.",
                      "additionalProperties": true
                    },
                    "space.tweet": {
                      "type": "object",
                      "description": "The wrapper tweet X mints so the Space can be shared, or null.",
                      "additionalProperties": true
                    },
                    "space.community_id": {
                      "type": "string",
                      "description": "Set when the Space is hosted inside a Community, otherwise null."
                    },
                    "space.mentioned_user_ids": {
                      "type": "object",
                      "description": "User ids X lists as mentioned by the Space. Ids only, not profiles.",
                      "additionalProperties": true
                    },
                    "space.admins": {
                      "type": "object",
                      "description": "Hosts and co-hosts, each { user_id, screen_name, display_name, avatar_url, periscope_user_id, is_verified, is_muted_by_admin, is_muted_by_guest, community_role, start }.",
                      "additionalProperties": true
                    },
                    "space.speakers": {
                      "type": "object",
                      "description": "Speakers, same shape as admins.",
                      "additionalProperties": true
                    },
                    "space.listeners": {
                      "type": "object",
                      "description": "Listeners, same shape as admins. Empty for an ended Space: X drops this roster once a Space finishes, while the audience counts above survive.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "space": {
                    "id": "1RKZzjkoYRAKB",
                    "title": "TIME TO BUILD!",
                    "state": "Ended",
                    "content_type": "visual_audio",
                    "media_key": "28_2042268179733643265",
                    "created_at": 1775749652198,
                    "scheduled_start": 1775840400000,
                    "started_at": 1775840398722,
                    "ended_at": 1775842790853,
                    "updated_at": 1775842791870,
                    "total_live_listeners": 264,
                    "total_replay_watched": 6290,
                    "is_space_available_for_replay": true,
                    "is_space_available_for_clipping": true,
                    "is_locked": false,
                    "is_muted": false,
                    "is_employee_only": false,
                    "no_incognito": false,
                    "disallow_join": false,
                    "is_subscribed": false,
                    "max_admin_capacity": 3,
                    "max_guest_sessions": 10,
                    "narrow_cast_space_type": 0,
                    "conversation_controls": 0,
                    "topics": [
                      {
                        "topic_id": "848920371311001600",
                        "name": "Technology"
                      },
                      {
                        "topic_id": "857879302733418496",
                        "name": "Entrepreneurship"
                      }
                    ],
                    "creator": {
                      "id": "825531272621654016",
                      "username": "TheBestOfAdam",
                      "name": "Adam Soccolich"
                    },
                    "tweet": {
                      "id": "2042648800989233184",
                      "text": "https://t.co/TARX17sERY"
                    },
                    "community_id": "1471580197908586507",
                    "mentioned_user_ids": [
                      "1254214946751049729"
                    ],
                    "admins": [
                      {
                        "user_id": "825531272621654016",
                        "screen_name": "TheBestOfAdam",
                        "display_name": "Adam Soccolich",
                        "avatar_url": "https://pbs.twimg.com/profile_images/...",
                        "periscope_user_id": "1WLERGNWdqRQb",
                        "is_verified": true,
                        "is_muted_by_admin": false,
                        "is_muted_by_guest": false,
                        "community_role": "Moderator",
                        "start": 1775840398860
                      }
                    ],
                    "speakers": [],
                    "listeners": []
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The Space id, the trailing token in a x.com/i/spaces/<id> URL. 5-32 alphanumeric characters.",
            "schema": {
              "type": "string",
              "description": "The Space id, the trailing token in a x.com/i/spaces/<id> URL. 5-32 alphanumeric characters.",
              "example": "1RKZzjkoYRAKB"
            },
            "example": "1RKZzjkoYRAKB"
          },
          {
            "name": "with_listeners",
            "in": "query",
            "required": false,
            "description": "Include the listener roster. Defaults to true. X does not retain this roster after a Space ends, so it comes back empty for an ended Space regardless of this flag.",
            "schema": {
              "type": "boolean",
              "description": "Include the listener roster. Defaults to true. X does not retain this roster after a Space ends, so it comes back empty for an ended Space regardless of this flag.",
              "example": "true"
            },
            "example": "true"
          },
          {
            "name": "with_replays",
            "in": "query",
            "required": false,
            "description": "Include replay availability and related metadata. Defaults to true.",
            "schema": {
              "type": "boolean",
              "description": "Include replay availability and related metadata. Defaults to true.",
              "example": "true"
            },
            "example": "true"
          }
        ]
      }
    },
    "/twitter/community/info": {
      "get": {
        "operationId": "community-info",
        "summary": "Community Info",
        "description": "Look up a single X Community by its numeric id and get back its name, description, member count, join policy, primary topic, posted rules and both banners. This endpoint returns the REDUCED form of the Community object: eight of its 24 fields come back empty here and are populated by Community Memberships instead, which the response table marks field by field. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/info?community_id=1493446837214187523\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/info\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"community_id\": \"1493446837214187523\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/info\");\nurl.search = new URLSearchParams({ community_id: \"1493446837214187523\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Metadata, rules and banners for one X Community.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "community": {
                      "allOf": [
                        {
                          "$ref": "#/components/schemas/Community"
                        }
                      ],
                      "description": "The community, or null with a 404 when the id resolves to nothing. This is the shared Community object, and this endpoint returns the REDUCED form of it: admin, invites_policy, question, search_tags and members_facepile_ids come back empty here, moderator_count comes back 0, and creator comes back with id and name null. Community Memberships returns the same 24 keys populated. Each field's own row says which endpoint fills it."
                    }
                  }
                },
                "example": {
                  "community": {
                    "id": "1828843041869713562",
                    "name": "Build In Public - SaaS",
                    "description": "Founders shipping in the open.",
                    "created_at": 1724865134102,
                    "member_count": 392,
                    "moderator_count": 0,
                    "join_policy": "RestrictedJoinRequestsRequireModeratorApproval",
                    "invites_policy": null,
                    "is_nsfw": false,
                    "question": null,
                    "primary_topic": {
                      "topic_id": null,
                      "name": "Software"
                    },
                    "search_tags": [],
                    "rules": [
                      {
                        "id": "1828843041869713570",
                        "name": "Be useful, not promotional",
                        "description": "Ship updates and ask real questions. Link drops with no context get removed."
                      },
                      {
                        "id": "1828843041869713571",
                        "name": "No paid promotion",
                        "description": null
                      }
                    ],
                    "banner_url": "https://pbs.twimg.com/community_banner_img/...",
                    "custom_banner": {
                      "url": "https://pbs.twimg.com/community_banner_img/...",
                      "width": 1500,
                      "height": 500
                    },
                    "default_banner": {
                      "url": "https://pbs.twimg.com/semantic_core_img/...",
                      "width": 1500,
                      "height": 500
                    },
                    "permalink": null,
                    "admin": null,
                    "creator": {
                      "id": null,
                      "username": "pizzaboy",
                      "name": null,
                      "verified": false,
                      "is_blue_verified": true
                    },
                    "members_facepile_ids": [],
                    "role": null,
                    "can_join": null,
                    "is_pinned": null,
                    "viewer_relationship_type": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "community_id",
            "in": "query",
            "required": true,
            "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL. Digits only, no leading zero.",
            "schema": {
              "type": "string",
              "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL. Digits only, no leading zero.",
              "example": "1493446837214187523"
            },
            "example": "1493446837214187523"
          }
        ]
      }
    },
    "/twitter/community/members": {
      "get": {
        "operationId": "community-members",
        "summary": "Community Members",
        "description": "Fetch the member roster of an X Community, cursor-paginated, with each row carrying that member's own role in the community: Admin, Moderator or Member. Admins and moderators appear in this list alongside ordinary members and are not grouped, so do not derive a moderator list by filtering the first page. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/members?community_id=1493446837214187523\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/members\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"community_id\": \"1493446837214187523\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/members\");\nurl.search = new URLSearchParams({ community_id: \"1493446837214187523\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/community/members?community_id=1493446837214187523&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.members | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.members[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/community/members\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"community_id\": \"1493446837214187523\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"members\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { community_id: \"1493446837214187523\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/community/members\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.members ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through a community's member roster, each row carrying that member's role.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "members": {
                      "type": "object",
                      "description": "Roster rows for this page, each { user, role }.",
                      "additionalProperties": true
                    },
                    "members[].user": {
                      "type": "object",
                      "description": "A REDUCED user profile: id, username, name, profile_image_url, is_blue_verified, verified, is_protected. It is smaller than the object User Info returns, on purpose, because X's roster operation sends no bio, no follower or following counts, no location, no website and no created_at. Those keys are ABSENT rather than null, so you can never mistake not-asked-for for zero.",
                      "additionalProperties": true
                    },
                    "members[].user.id": {
                      "type": "string",
                      "description": "Numeric user id as a string."
                    },
                    "members[].user.username": {
                      "type": "string",
                      "description": "Handle without the leading @."
                    },
                    "members[].user.name": {
                      "type": "string",
                      "description": "Display name."
                    },
                    "members[].user.profile_image_url": {
                      "type": "string",
                      "description": "Avatar URL. X sends the _normal size on this operation and it is passed through unchanged rather than rewritten to a larger variant that X did not send."
                    },
                    "members[].user.is_blue_verified": {
                      "type": "boolean",
                      "description": "Blue (paid) verification."
                    },
                    "members[].user.verified": {
                      "type": "boolean",
                      "description": "Legacy (official or notable) verification. A different thing from is_blue_verified; never conflate them."
                    },
                    "members[].user.is_protected": {
                      "type": "boolean",
                      "description": "Whether the account is protected (locked)."
                    },
                    "members[].role": {
                      "type": "string",
                      "description": "THAT MEMBER's role in this community: Admin, Moderator or Member. This one is NOT caller-relative, unlike the role field on the community object itself, and it is the reason this endpoint exists. Null when X did not label the row, which is not the same as Member: a roster we cannot role-label has unknown roles, and reading null as Member would deny moderators."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when X sent none. Absence of this cursor is the only end-of-list signal X gives on this operation."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned rows and carried a usable next_cursor. Computed here; X sends no has_more of its own on this operation."
                    }
                  }
                },
                "example": {
                  "members": [
                    {
                      "user": {
                        "id": "1281109705495130113",
                        "username": "pizzaboy",
                        "name": "Dan Holdsworth",
                        "profile_image_url": "https://pbs.twimg.com/profile_images/..._normal.png",
                        "is_blue_verified": true,
                        "verified": false,
                        "is_protected": false
                      },
                      "role": "Admin"
                    },
                    {
                      "user": {
                        "id": "44196397",
                        "username": "devjane",
                        "name": "Jane",
                        "profile_image_url": "https://pbs.twimg.com/profile_images/..._normal.png",
                        "is_blue_verified": false,
                        "verified": false,
                        "is_protected": false
                      },
                      "role": "Member"
                    }
                  ],
                  "next_cursor": "RG9uZUZvck5vd0N1cnNvcg==",
                  "has_more": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "community_id",
            "in": "query",
            "required": true,
            "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
            "schema": {
              "type": "string",
              "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
              "example": "1493446837214187523"
            },
            "example": "1493446837214187523"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Page size. Defaults to 20 and is clamped to 1-100, so count=500 returns 100 rather than erroring. A non-numeric value is a 400.",
            "schema": {
              "type": "integer",
              "description": "Page size. Defaults to 20 and is clamped to 1-100, so count=500 returns 100 rather than erroring. A non-numeric value is a 400.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/community/moderators": {
      "get": {
        "operationId": "community-moderators",
        "summary": "Community Moderators",
        "description": "Fetch the moderators and admins of an X Community, cursor-paginated, in the same row shape Community Members returns. This is a separate upstream operation rather than a filter over the member roster, because moderators are interleaved through that roster at arbitrary positions. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/moderators?community_id=1493446837214187523\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/moderators\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"community_id\": \"1493446837214187523\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/moderators\");\nurl.search = new URLSearchParams({ community_id: \"1493446837214187523\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/community/moderators?community_id=1493446837214187523&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.members | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.members[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/community/moderators\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"community_id\": \"1493446837214187523\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"members\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { community_id: \"1493446837214187523\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/community/moderators\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.members ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through a community's moderators and admins.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "members": {
                      "type": "object",
                      "description": "Moderator rows for this page, each { user, role }. The key is members, not moderators: the row shape is identical to Community Members on purpose, so one type serves both endpoints and the two cannot drift.",
                      "additionalProperties": true
                    },
                    "members[].user": {
                      "type": "object",
                      "description": "The same REDUCED user profile Community Members returns: id, username, name, profile_image_url, is_blue_verified, verified, is_protected. No bio, no follower counts, no created_at, because X's roster operation does not send them.",
                      "additionalProperties": true
                    },
                    "members[].role": {
                      "type": "string",
                      "description": "That account's role in this community, expected to be Moderator or Admin here. Like the role on a Community Members row, this one is NOT caller-relative and is returned in full: it describes that account, is identical for every caller, and is the content of the endpoint. It is returned rather than assumed constant, so a moderator roster that starts carrying a mixed role set surfaces instead of being silently flattened. Null when X did not label the row, which is not the same as Member."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when X sent none."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned rows and carried a usable next_cursor. Computed here; X sends no has_more of its own."
                    }
                  }
                },
                "example": {
                  "members": [
                    {
                      "user": {
                        "id": "1281109705495130113",
                        "username": "pizzaboy",
                        "name": "Dan Holdsworth",
                        "profile_image_url": "https://pbs.twimg.com/profile_images/..._normal.png",
                        "is_blue_verified": true,
                        "verified": false,
                        "is_protected": false
                      },
                      "role": "Admin"
                    },
                    {
                      "user": {
                        "id": "3310215544",
                        "username": "buildlogs",
                        "name": "Build Logs",
                        "profile_image_url": "https://pbs.twimg.com/profile_images/..._normal.png",
                        "is_blue_verified": true,
                        "verified": false,
                        "is_protected": false
                      },
                      "role": "Moderator"
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "community_id",
            "in": "query",
            "required": true,
            "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
            "schema": {
              "type": "string",
              "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
              "example": "1493446837214187523"
            },
            "example": "1493446837214187523"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
            "schema": {
              "type": "integer",
              "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/community/tweets": {
      "get": {
        "operationId": "community-tweets",
        "summary": "Community Tweets",
        "description": "Fetch the post timeline of an X Community, cursor-paginated as full tweet objects, with optional ordering control. The community's pinned post is returned as its own field rather than mixed into the feed, because X delivers it under a different timeline instruction and does not repeat it in the feed. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/tweets?community_id=1493446837214187523\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/tweets\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"community_id\": \"1493446837214187523\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/tweets\");\nurl.search = new URLSearchParams({ community_id: \"1493446837214187523\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/community/tweets?community_id=1493446837214187523&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.tweets | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.tweets[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/community/tweets\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"community_id\": \"1493446837214187523\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"tweets\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { community_id: \"1493446837214187523\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/community/tweets\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.tweets ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Page through a community's post timeline, with the pinned post returned separately.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pinned": {
                      "type": "object",
                      "description": "The community's PINNED post as a full tweet object, or null when the community has none. It is its own field and is NOT included in tweets: X delivers it under a separate timeline instruction and does not repeat it in the feed, so a parser that reads only the feed drops it without a trace. In the captured community it was the rules post, which is usually the single most useful item in the response. A client that wants one flat list should read pinned first, then tweets.",
                      "additionalProperties": true
                    },
                    "tweets": {
                      "type": "array",
                      "description": "The community's posts for this page, as full tweet objects. The pinned post is excluded, so a flat list is pinned followed by tweets with no duplicate. X attaches a caller-relative community moderation state to each tweet upstream; it is never extracted, because on a pooled read it would describe our rotating pool account rather than you.",
                      "items": {
                        "$ref": "#/components/schemas/Tweet"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when there is none. Pass it back as ?cursor=."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned tweets and carried a usable next_cursor. False on the final page."
                    }
                  }
                },
                "example": {
                  "pinned": {
                    "id": "1926022758195921145",
                    "text": "Community rules: be useful, no unsolicited DMs, no engagement bait.",
                    "created_at": "Fri May 23 09:14:02 +0000 2026",
                    "author": {
                      "id": "1281109705495130113",
                      "username": "pizzaboy",
                      "name": "Dan Holdsworth"
                    },
                    "favorite_count": 118
                  },
                  "tweets": [
                    {
                      "id": "1926104411223344556",
                      "text": "Shipped the billing rewrite this morning. Numbers in the thread.",
                      "created_at": "Fri May 23 14:41:19 +0000 2026",
                      "author": {
                        "id": "44196397",
                        "username": "devjane",
                        "name": "Jane"
                      },
                      "favorite_count": 26,
                      "reply_count": 4
                    }
                  ],
                  "next_cursor": "DAABCgABF...",
                  "has_more": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "community_id",
            "in": "query",
            "required": true,
            "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
            "schema": {
              "type": "string",
              "description": "The numeric community id, the digits in a x.com/i/communities/<id> URL.",
              "example": "1493446837214187523"
            },
            "example": "1493446837214187523"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
            "schema": {
              "type": "integer",
              "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "ranking_mode",
            "in": "query",
            "required": false,
            "description": "Ordering, sent to X as a real upstream parameter rather than applied as a local sort. Recency is the default and the only value confirmed against a live capture. Relevance is accepted because X's own community tab offers exactly two orderings, but it has not been confirmed live, so do not depend on it. Any other value is a 400.",
            "schema": {
              "type": "string",
              "description": "Ordering, sent to X as a real upstream parameter rather than applied as a local sort. Recency is the default and the only value confirmed against a live capture. Relevance is accepted because X's own community tab offers exactly two orderings, but it has not been confirmed live, so do not depend on it. Any other value is a 400.",
              "example": "Recency"
            },
            "example": "Recency"
          }
        ]
      }
    },
    "/twitter/community/memberships": {
      "get": {
        "operationId": "community-memberships",
        "summary": "Community Memberships",
        "description": "The inverse relation: given a numeric X user id, list the communities that account belongs to, cursor-paginated. Each row is the FULL community object, and it is the most populated form of it this API returns: admin, invites_policy, question, search_tags, members_facepile_ids and a real moderator_count all arrive here and do not on Community Info. Profiling an account's community footprint takes one call per page rather than a follow-up lookup per community. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/memberships?user_id=1281109705495130113\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/memberships\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"user_id\": \"1281109705495130113\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/memberships\");\nurl.search = new URLSearchParams({ user_id: \"1281109705495130113\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/community/memberships?user_id=1281109705495130113&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.communities | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.communities[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/community/memberships\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"user_id\": \"1281109705495130113\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"communities\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { user_id: \"1281109705495130113\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/community/memberships\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.communities ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "List every community a given account belongs to.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "communities": {
                      "type": "array",
                      "description": "The communities this account belongs to, for this page. Each entry is the shared Community object, the same 24 keys Community Info returns, so a client that renders one can render the other. It is also the MORE POPULATED of the two: admin, invites_policy, question, search_tags, members_facepile_ids, a real moderator_count and a full creator profile all come back here and do not on Community Info. Deduplicated by id.",
                      "items": {
                        "$ref": "#/components/schemas/Community"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when there is none."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned communities and carried a usable next_cursor. False on the final page."
                    }
                  }
                },
                "example": {
                  "communities": [
                    {
                      "id": "1828843041869713562",
                      "name": "Build In Public - SaaS",
                      "description": "Founders shipping in the open.",
                      "created_at": 1724865134102,
                      "member_count": 392,
                      "moderator_count": 1,
                      "join_policy": "RestrictedJoinRequestsRequireModeratorApproval",
                      "invites_policy": "MemberInvitesAllowed",
                      "is_nsfw": false,
                      "question": "What are you currently building?",
                      "primary_topic": {
                        "topic_id": "303",
                        "name": "Software"
                      },
                      "search_tags": [
                        "saas",
                        "buildinpublic"
                      ],
                      "rules": [
                        {
                          "id": "1828843041869713570",
                          "name": "Be useful, not promotional",
                          "description": null
                        }
                      ],
                      "banner_url": "https://pbs.twimg.com/community_banner_img/...",
                      "permalink": null,
                      "admin": {
                        "id": "1281109705495130113",
                        "username": "pizzaboy",
                        "name": "Dan Holdsworth"
                      },
                      "creator": {
                        "id": "1281109705495130113",
                        "username": "pizzaboy",
                        "name": "Dan Holdsworth"
                      },
                      "members_facepile_ids": [
                        "1281109705495130113"
                      ],
                      "role": null,
                      "can_join": null,
                      "is_pinned": null,
                      "viewer_relationship_type": null
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "The numeric X user id, NOT a handle and NOT a community id. Resolve a @handle to an id with User Info first; doing that resolution silently here would turn one billed read into two.",
            "schema": {
              "type": "string",
              "description": "The numeric X user id, NOT a handle and NOT a community id. Resolve a @handle to an id with User Info first; doing that resolution silently here would turn one billed read into two.",
              "example": "1281109705495130113"
            },
            "example": "1281109705495130113"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call."
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
            "schema": {
              "type": "integer",
              "description": "Page size. Defaults to 20 and is clamped to 1-100. A non-numeric value is a 400.",
              "example": "20"
            },
            "example": "20"
          }
        ]
      }
    },
    "/twitter/community/about": {
      "get": {
        "operationId": "community-about",
        "summary": "Community About",
        "description": "The About tab for one community: its moderators, and a preview of its members, both returned as FULL user profiles with bio, follower and following counts, tweet counts, location, website, banner and join date. Community Members and Community Moderators return a reduced row instead, so this is the endpoint that answers who runs a community in one call rather than one call plus a profile lookup per person. It is not paginated, because the upstream operation is not. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/about?community_id=1493446837214187523\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/about\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"community_id\": \"1493446837214187523\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/about\");\nurl.search = new URLSearchParams({ community_id: \"1493446837214187523\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "A community's moderators and a members preview, as full profiles.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "moderators": {
                      "type": "array",
                      "description": "The community's moderators, as full user profiles. Same object User Info returns.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "members": {
                      "type": "array",
                      "description": "A preview of the community's members, as full user profiles. X caps this at 10 rows on the underlying tab, so treat it as a sample and not a roster.",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "moderators_truncated": {
                      "type": "boolean",
                      "description": "True when X indicated there are more moderators than it sent. Read off X's own show-more marker, not inferred from the row count, so a community with exactly as many moderators as fit is reported correctly."
                    },
                    "members_truncated": {
                      "type": "boolean",
                      "description": "Same, for the members preview. True in practice for any community with more than 10 members. Page the full list with Community Members."
                    },
                    "other_sections": {
                      "type": "array",
                      "description": "Any section of the About tab this API does not yet model, each carrying id, title, users and more_url. Empty on every community observed so far. It exists so a section X adds later reaches you rather than being silently dropped.",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                },
                "example": {
                  "moderators": [
                    {
                      "id": "88403351",
                      "username": "iuditg",
                      "name": "Udit Goenka",
                      "description": "Building in public.",
                      "followers_count": 60868,
                      "following_count": 372,
                      "tweet_count": 46535,
                      "location": "India",
                      "url": "https://example.com",
                      "created_at": "Sun Nov 08 11:49:55 +0000 2009",
                      "profile_image_url": "https://pbs.twimg.com/profile_images/.../photo_normal.jpg",
                      "is_blue_verified": true
                    }
                  ],
                  "members": [
                    {
                      "id": "2535083002",
                      "username": "sachikantaraul",
                      "name": "Sachikanta Raul",
                      "description": "Indie hacker.",
                      "followers_count": 41,
                      "following_count": 300,
                      "tweet_count": 1204,
                      "location": "India",
                      "url": null,
                      "created_at": "Thu May 08 13:15:44 +0000 2014",
                      "profile_image_url": "https://pbs.twimg.com/profile_images/.../photo_normal.jpg",
                      "is_blue_verified": true
                    }
                  ],
                  "moderators_truncated": false,
                  "members_truncated": true,
                  "other_sections": []
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "community_id",
            "in": "query",
            "required": true,
            "description": "The numeric X community id, the digits in x.com/i/communities/<id>.",
            "schema": {
              "type": "string",
              "description": "The numeric X community id, the digits in x.com/i/communities/<id>.",
              "example": "1493446837214187523"
            },
            "example": "1493446837214187523"
          }
        ]
      }
    },
    "/twitter/community/search": {
      "get": {
        "operationId": "community-search",
        "summary": "Community Search",
        "description": "Find communities by keyword, cursor-paginated. This is the discovery step the rest of this family assumes: every other community endpoint starts from a community id, and this is the one that produces one. Each hit is a compact record, id, name, member count, nsfw flag, topic name, banners and the facepile avatars, which is exactly what X's search operation sends and nothing more. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Communities"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/community/search?query=build%20in%20public\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/community/search\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"query\": \"build in public\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/community/search\");\nurl.search = new URLSearchParams({ query: \"build in public\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/community/search?query=build%20in%20public&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.communities | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.communities[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/community/search\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"query\": \"build in public\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"communities\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { query: \"build in public\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/community/search\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.communities ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "Search X Communities by keyword.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "communities": {
                      "type": "array",
                      "description": "The matching communities for this page. A COMPACT record, not the full Community object Community Info returns: id, name, member_count, is_nsfw, primary_topic, banner_url, custom_banner, default_banner and member_avatar_urls. Take an id from here and call Community Info for the rest.",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when there is none."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when this page returned communities and carried a usable next_cursor."
                    }
                  }
                },
                "example": {
                  "communities": [
                    {
                      "id": "1493446837214187523",
                      "name": "Build in Public",
                      "member_count": 265158,
                      "is_nsfw": false,
                      "primary_topic": {
                        "topic_id": null,
                        "name": "Entrepreneurship"
                      },
                      "banner_url": "https://pbs.twimg.com/community_banner_img/...",
                      "custom_banner": {
                        "url": "https://pbs.twimg.com/community_banner_img/...",
                        "width": 805,
                        "height": 322
                      },
                      "default_banner": {
                        "url": "https://pbs.twimg.com/media/....jpg",
                        "width": 1200,
                        "height": 480
                      },
                      "member_avatar_urls": [
                        "https://pbs.twimg.com/profile_images/.../photo_normal.jpg"
                      ]
                    }
                  ],
                  "next_cursor": "WzM1Mi4xMzgzLDE5NDM4NDIyMDQwNzU4NjgyMzhd",
                  "has_more": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "query",
            "in": "query",
            "required": true,
            "description": "The keyword to search for. 1 to 500 characters.",
            "schema": {
              "type": "string",
              "description": "The keyword to search for. 1 to 500 characters.",
              "example": "build in public"
            },
            "example": "build in public"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor. Omit on the first call."
            }
          }
        ]
      }
    },
    "/twitter/media/upload": {
      "post": {
        "operationId": "media-upload",
        "summary": "Upload Media",
        "description": "Upload a base64-encoded image as the authenticated account and receive a media_id you can attach when creating a tweet. Runs as your own logged-in account. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/media/upload\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"media_data\": \"iVBORw0KGgoAAAANSUhEUgAA...\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/media/upload\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"media_data\": \"iVBORw0KGgoAAAANSUhEUgAA...\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/media/upload\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ media_data: \"iVBORw0KGgoAAAANSUhEUgAA...\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Upload an image and get a media_id to attach to a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the upload succeeded (media_id is present)."
                    },
                    "media_id": {
                      "type": "string",
                      "description": "The uploaded media's ID; pass it to tweet/create to attach the image."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "media_id": "1899999999999999999"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "media_data": {
                    "type": "string",
                    "description": "Base64-encoded image bytes, sent in the JSON request body.",
                    "example": "iVBORw0KGgoAAAANSUhEUgAA..."
                  }
                },
                "required": [
                  "media_data"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/media/status": {
      "get": {
        "operationId": "media-status",
        "summary": "Media Status",
        "description": "Return the async processing state of a media_id from Upload Media, so a caller can verify readiness before attaching a video, GIF, or large-media id to a tweet. Runs as your own logged-in account. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/media/status?media_id=1899999999999999999\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/media/status\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"media_id\": \"1899999999999999999\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/media/status\");\nurl.search = new URLSearchParams({ media_id: \"1899999999999999999\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Check the async processing state of an uploaded media_id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "media_id": {
                      "type": "string",
                      "description": "Echo of the media_id you queried."
                    },
                    "state": {
                      "type": "string",
                      "description": "Processing state: pending, in_progress, succeeded, or failed."
                    },
                    "check_after_secs": {
                      "type": "integer",
                      "description": "Seconds to wait before polling again while the state is pending or in_progress; 0 once processing has finished."
                    },
                    "progress_percent": {
                      "type": "integer",
                      "description": "Percentage of processing completed, from 0 to 100."
                    },
                    "error": {
                      "type": "string",
                      "description": "Failure reason, present only when state is failed; omitted otherwise."
                    }
                  }
                },
                "example": {
                  "media_id": "1899999999999999999",
                  "state": "succeeded",
                  "check_after_secs": 0,
                  "progress_percent": 100
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "media_id",
            "in": "query",
            "required": true,
            "description": "Numeric media ID (as a string) returned by media/upload.",
            "schema": {
              "type": "string",
              "description": "Numeric media ID (as a string) returned by media/upload.",
              "example": "1899999999999999999"
            },
            "example": "1899999999999999999"
          }
        ]
      }
    },
    "/twitter/list/add_member": {
      "post": {
        "operationId": "list-add-member",
        "summary": "Add List Member",
        "description": "Add an account to a List owned by your registered X session. Returns the List's member_count as proof the membership change landed. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/list/add_member\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{{\"list_id\": \"1234567890123456789\", \"user_id\": \"745273\"}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/list/add_member\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"list_id\": \"1234567890123456789\", \"user_id\": \"745273\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/list/add_member\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ list_id: \"1234567890123456789\", user_id: \"745273\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Add one account to a Twitter/X List you own.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the membership change applied."
                    },
                    "action": {
                      "type": "string",
                      "description": "The membership action performed."
                    },
                    "list_id": {
                      "type": "string",
                      "description": "The List the write targeted."
                    },
                    "user_id": {
                      "type": "string",
                      "description": "The account the write targeted."
                    },
                    "member_count": {
                      "type": "object",
                      "description": "The List's member count after the write, read back from X as proof. Null when X returned no list object, which is the not-applied signal.",
                      "additionalProperties": true
                    },
                    "list": {
                      "type": "object",
                      "description": "The List object X returned after the write.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "action": "add_member",
                  "list_id": "1234567890123456789",
                  "user_id": "745273",
                  "member_count": 42,
                  "list": {
                    "id": "1234567890123456789",
                    "name": "Founders",
                    "member_count": 42
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "list_id": {
                    "type": "string",
                    "description": "Numeric ID of the List you own.",
                    "example": "1234567890123456789"
                  },
                  "user_id": {
                    "type": "string",
                    "description": "Numeric ID of the account to add.",
                    "example": "745273"
                  }
                },
                "required": [
                  "list_id",
                  "user_id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/list/remove_member": {
      "post": {
        "operationId": "list-remove-member",
        "summary": "Remove List Member",
        "description": "Remove an account from a List owned by your registered X session. Returns the List's member_count as proof the membership change landed. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/list/remove_member\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{{\"list_id\": \"1234567890123456789\", \"user_id\": \"745273\"}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/list/remove_member\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"list_id\": \"1234567890123456789\", \"user_id\": \"745273\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/list/remove_member\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ list_id: \"1234567890123456789\", user_id: \"745273\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Remove one account from a Twitter/X List you own.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the membership change applied."
                    },
                    "action": {
                      "type": "string",
                      "description": "The membership action performed."
                    },
                    "list_id": {
                      "type": "string",
                      "description": "The List the write targeted."
                    },
                    "user_id": {
                      "type": "string",
                      "description": "The account the write targeted."
                    },
                    "member_count": {
                      "type": "object",
                      "description": "The List's member count after the write, read back from X as proof. Null when X returned no list object, which is the not-applied signal.",
                      "additionalProperties": true
                    },
                    "list": {
                      "type": "object",
                      "description": "The List object X returned after the write.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "action": "remove_member",
                  "list_id": "1234567890123456789",
                  "user_id": "745273",
                  "member_count": 41,
                  "list": {
                    "id": "1234567890123456789",
                    "name": "Founders",
                    "member_count": 41
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "list_id": {
                    "type": "string",
                    "description": "Numeric ID of the List you own.",
                    "example": "1234567890123456789"
                  },
                  "user_id": {
                    "type": "string",
                    "description": "Numeric ID of the account to remove.",
                    "example": "745273"
                  }
                },
                "required": [
                  "list_id",
                  "user_id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/list/create": {
      "post": {
        "operationId": "list-create",
        "summary": "Create List",
        "description": "Create a List owned by your registered X session, with a name and an optional description and privacy flag. Populate it afterwards with Add List Member. Cost: $0.0016 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/list/create\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{{\"name\": \"Founders\"}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/list/create\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"name\": \"Founders\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/list/create\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ name: \"Founders\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Create a new Twitter/X List owned by your session.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the List was created."
                    },
                    "list": {
                      "type": "object",
                      "description": "The List object X returned, including its new numeric id.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "list": {
                    "id": "1234567890123456789",
                    "name": "Founders",
                    "description": "People building in public.",
                    "member_count": 0
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Display name for the new List.",
                    "example": "Founders"
                  },
                  "description": {
                    "type": "string",
                    "description": "Optional description shown on the List.",
                    "example": "People building in public."
                  },
                  "is_private": {
                    "type": "boolean",
                    "description": "Whether the List is private. Private Lists are not readable by the public List read endpoints.",
                    "example": "false"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/tweet/favorite": {
      "post": {
        "operationId": "tweet-favorite",
        "summary": "Like Tweet",
        "description": "Like a tweet as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/favorite?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/favorite\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/favorite\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Like (favorite) a tweet on behalf of an authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the like is recorded."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to like. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to like. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to like. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to like. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/unfavorite": {
      "post": {
        "operationId": "tweet-unfavorite",
        "summary": "Unlike Tweet",
        "description": "Remove a previously recorded like from a tweet as the authenticated account. Requires a logged-in session. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/unfavorite?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/unfavorite\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/unfavorite\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a like (unfavorite) from a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the like is removed."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to unlike. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to unlike. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to unlike. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to unlike. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/retweet": {
      "post": {
        "operationId": "tweet-retweet",
        "summary": "Retweet",
        "description": "Retweet a tweet as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/retweet?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/retweet\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/retweet\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Retweet a tweet on behalf of an authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the retweet is recorded."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to retweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to retweet. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to retweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to retweet. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/unretweet": {
      "post": {
        "operationId": "tweet-unretweet",
        "summary": "Undo Retweet",
        "description": "Undo a previously recorded retweet as the authenticated account. Requires a logged-in session. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/unretweet?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/unretweet\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/unretweet\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a retweet from a tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the retweet is removed."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to un-retweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to un-retweet. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to un-retweet. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to un-retweet. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/bookmark": {
      "post": {
        "operationId": "tweet-bookmark",
        "summary": "Bookmark Tweet",
        "description": "Bookmark a tweet as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/bookmark?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/bookmark\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/bookmark\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Add a tweet to the authenticated account's bookmarks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the bookmark is recorded."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to bookmark. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to bookmark. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to bookmark. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to bookmark. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/unbookmark": {
      "post": {
        "operationId": "tweet-unbookmark",
        "summary": "Remove Bookmark",
        "description": "Remove a previously saved bookmark as the authenticated account. Requires a logged-in session. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/unbookmark?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/unbookmark\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"id\": \"1759123456789012345\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/unbookmark\");\nurl.search = new URLSearchParams({ \"id\": \"1759123456789012345\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a tweet from the authenticated account's bookmarks.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the bookmark is removed."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to un-bookmark. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to un-bookmark. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Full status URL of the tweet to un-bookmark. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Full status URL of the tweet to un-bookmark. Provide either id or url.",
              "example": "https://x.com/naval/status/1759123456789012345"
            },
            "example": "https://x.com/naval/status/1759123456789012345"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/user/follow": {
      "post": {
        "operationId": "user-follow",
        "summary": "Follow User",
        "description": "Follow a user as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/user/follow?user_id=44196397\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/user/follow\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"user_id\": \"44196397\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/follow\");\nurl.search = new URLSearchParams({ \"user_id\": \"44196397\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Follow a user on behalf of an authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the follow is recorded."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the user to follow.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the user to follow.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/user/unfollow": {
      "post": {
        "operationId": "user-unfollow",
        "summary": "Unfollow User",
        "description": "Unfollow a user as the authenticated account. Requires a logged-in session for the acting account. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/user/unfollow?user_id=44196397\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\"\n# Add &proxy=http://user:pass@host:port to route through your own clean IP."
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/user/unfollow\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={ \"user_id\": \"44196397\" },  # add \"proxy\": \"http://user:pass@host:port\" to use your own IP\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/user/unfollow\");\nurl.search = new URLSearchParams({ \"user_id\": \"44196397\" }).toString();\n// Add proxy: \"http://user:pass@host:port\" above to route through your own clean IP.\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Unfollow a user on behalf of an authenticated account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the unfollow is recorded."
                    }
                  }
                },
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "user_id",
            "in": "query",
            "required": true,
            "description": "Numeric ID of the user to unfollow.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the user to unfollow.",
              "example": "44196397"
            },
            "example": "44196397"
          },
          {
            "name": "proxy",
            "in": "query",
            "required": false,
            "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default.",
            "schema": {
              "type": "string",
              "description": "Optional. Pass your own proxy (http(s)/socks URL) to egress the write through your clean IP for best success; if omitted, we use the session's proxy / our default."
            }
          }
        ]
      }
    },
    "/twitter/tweet/create": {
      "post": {
        "operationId": "tweet-create",
        "summary": "Create Tweet",
        "description": "Post a new tweet as the account behind your registered session. Supports plain text, up to 4 image media_ids (from a prior media/upload), a reply (reply_to), and a quote (quote). Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/create\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"text\": \"Shipping cursor-paginated bookmarks today.\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/create\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"text\": \"Shipping cursor-paginated bookmarks today.\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/tweet/create\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ text: \"Shipping cursor-paginated bookmarks today.\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Post a tweet as your registered account: text, media, reply, or quote.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the tweet was posted."
                    },
                    "tweet_id": {
                      "type": "string",
                      "description": "Numeric ID of the created tweet, or null if the ID could not be resolved."
                    },
                    "url": {
                      "type": "string",
                      "description": "Canonical x.com URL of the created tweet, or null."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "tweet_id": "1759123456789012345",
                  "url": "https://x.com/i/status/1759123456789012345"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "description": "The tweet body.",
                    "example": "Shipping cursor-paginated bookmarks today."
                  },
                  "media_ids": {
                    "type": "string",
                    "description": "Up to 4 media IDs from media/upload, as a comma-separated string or JSON array. Omit for a text-only tweet.",
                    "example": "1899999999999999999"
                  },
                  "reply_to": {
                    "type": "string",
                    "description": "ID of the tweet to reply to (send it as a string; X IDs are 19 digits). Omit for a top-level tweet.",
                    "example": "2080297101888733302"
                  },
                  "quote": {
                    "type": "string",
                    "description": "ID of the tweet to quote (send it as a string; X IDs are 19 digits).",
                    "example": "1900000000000000000"
                  }
                },
                "required": [
                  "text"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/tweet/delete": {
      "post": {
        "operationId": "tweet-delete",
        "summary": "Delete Tweet",
        "description": "Delete a tweet owned by the account behind your registered session. Identify it by id or url (read from the query string). Requires a registered session. Billed at $0.0008 per call, the same as a standard read. Cost: $0.0008 per call.",
        "tags": [
          "Write Actions"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/tweet/delete?id=1759123456789012345\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/tweet/delete\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"1759123456789012345\"},\n)\nresp.raise_for_status()\nprint(resp.json())"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/tweet/delete\");\nurl.search = new URLSearchParams({ id: \"1759123456789012345\" }).toString();\nconst resp = await fetch(url, {\n  method: \"POST\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconsole.log(await resp.json());"
          }
        ],
        "responses": {
          "200": {
            "description": "Delete one of your registered account's tweets by ID or status URL.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the delete succeeded (mirrors deleted)."
                    },
                    "deleted": {
                      "type": "boolean",
                      "description": "True when X confirmed the tweet was deleted."
                    },
                    "tweet_id": {
                      "type": "string",
                      "description": "The numeric ID that was deleted."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "deleted": true,
                  "tweet_id": "1759123456789012345"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Numeric ID of the tweet to delete. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Numeric ID of the tweet to delete. Provide either id or url.",
              "example": "1759123456789012345"
            },
            "example": "1759123456789012345"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Status URL of the tweet to delete, for example https://x.com/you/status/1759123456789012345. Provide either id or url.",
            "schema": {
              "type": "string",
              "description": "Status URL of the tweet to delete, for example https://x.com/you/status/1759123456789012345. Provide either id or url."
            }
          }
        ]
      }
    },
    "/twitter/article/create": {
      "post": {
        "operationId": "article-create",
        "summary": "Create Article",
        "description": "Start a new draft Article as the account behind your registered session, and return its entity id, ready for Update Title / Update Content. The draft is empty until you call those. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/create\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/create\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/create\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Start a new draft article. No request body required.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the draft was created."
                    },
                    "article": {
                      "type": "object",
                      "description": "The new draft article: id (base64 entity id, pass this to every other article/* call), rest_id (numeric string), title (null until set), preview_text, lifecycle (Draft), content_state ({ blocks: [], entityMap: [] }, empty until Update Content), cover_media (null), media_entities ([]), author (user profile object), created_at_secs, modified_at_secs, first_published_at_secs (null), visibility_setting (null), tweet_id (null until published), and public_url (null until published).",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": null,
                    "preview_text": "",
                    "lifecycle": "Draft",
                    "content_state": {
                      "blocks": [],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400000,
                    "first_published_at_secs": null,
                    "visibility_setting": null,
                    "tweet_id": null,
                    "public_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/article/update_title": {
      "post": {
        "operationId": "article-update-title",
        "summary": "Update Article Title",
        "description": "Set the title of an article you own, identified by its entity id. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/update_title\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"title\": \"Why we rebuilt our onboarding from scratch\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/update_title\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"title\": \"Why we rebuilt our onboarding from scratch\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/update_title\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", title: \"Why we rebuilt our onboarding from scratch\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Set the title on a draft or published article.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the title was updated."
                    },
                    "article": {
                      "type": "object",
                      "description": "The updated article, full shape: id, rest_id, title, preview_text, lifecycle, content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "",
                    "lifecycle": "Draft",
                    "content_state": {
                      "blocks": [],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400120,
                    "first_published_at_secs": null,
                    "visibility_setting": null,
                    "tweet_id": null,
                    "public_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  },
                  "title": {
                    "type": "string",
                    "description": "The new title text.",
                    "example": "Why we rebuilt our onboarding from scratch"
                  }
                },
                "required": [
                  "id",
                  "title"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/article/update_cover_media": {
      "post": {
        "operationId": "article-update-cover-media",
        "summary": "Update Article Cover Image",
        "description": "Set the cover image on an article you own, identified by its entity id. This attaches media you have already uploaded; it does not upload anything itself, so call media/upload first and pass the media_id it returns. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/update_cover_media\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"media_id\": \"2088949698573090816\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/update_cover_media\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"media_id\": \"2088949698573090816\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/update_cover_media\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", media_id: \"2088949698573090816\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Attach an uploaded image as an article's cover.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the cover image was attached."
                    },
                    "article": {
                      "type": "object",
                      "description": "The updated article, full shape, with cover_media now populated: id, rest_id, title, preview_text, lifecycle, content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "",
                    "lifecycle": "Draft",
                    "content_state": {
                      "blocks": [],
                      "entityMap": []
                    },
                    "cover_media": {
                      "id": "QXBpTWVkaWE6...",
                      "media_id": "2088949698573090816",
                      "media_key": "3_2088949698573090816",
                      "original_img_url": "https://pbs.twimg.com/media/....jpg",
                      "original_img_width": 1600,
                      "original_img_height": 900,
                      "color_palette": []
                    },
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400300,
                    "first_published_at_secs": null,
                    "visibility_setting": null,
                    "tweet_id": null,
                    "public_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  },
                  "media_id": {
                    "type": "string",
                    "description": "The media id returned by media/upload for the image you want to use as the cover.",
                    "example": "2088949698573090816"
                  },
                  "media_category": {
                    "type": "string",
                    "description": "X's media category for the upload. Defaults to DraftTweetImage, which is what the X article editor itself sends. Only override this if you know X expects a different category for your media.",
                    "example": "DraftTweetImage"
                  }
                },
                "required": [
                  "id",
                  "media_id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/article/update_content": {
      "post": {
        "operationId": "article-update-content",
        "summary": "Update Article Content",
        "description": "Replace the body of an article you own with a new content_state, identified by its entity id. content_state is Draft.js editor-state JSON ({ blocks: [...], entityMap: [...] }) that you build client-side; it is passed through to X verbatim and not validated on our side. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/update_content\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"content_state\": {\"blocks\":[{\"key\":\"a1b2c\",\"text\":\"Opening paragraph.\",\"type\":\"unstyled\",\"depth\":0,\"inlineStyleRanges\":[],\"entityRanges\":[]}],\"entityMap\":{}}}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/update_content\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", \"content_state\": {\"blocks\": [{\"key\": \"a1b2c\", \"text\": \"Opening paragraph.\", \"type\": \"unstyled\", \"depth\": 0, \"inlineStyleRanges\": [], \"entityRanges\": []}], \"entityMap\": {}}},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/update_content\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\", content_state: { blocks: [{ key: \"a1b2c\", text: \"Opening paragraph.\", type: \"unstyled\", depth: 0, inlineStyleRanges: [], entityRanges: [] }], entityMap: {} } }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Replace an article's body with a new Draft.js content_state.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the content was updated."
                    },
                    "article": {
                      "type": "object",
                      "description": "The updated article, full shape: id, rest_id, title, preview_text, lifecycle, content_state (your new blocks/entityMap, echoed back), cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "Opening paragraph.",
                    "lifecycle": "Draft",
                    "content_state": {
                      "blocks": [
                        {
                          "key": "a1b2c",
                          "text": "Opening paragraph.",
                          "type": "unstyled",
                          "depth": 0,
                          "inlineStyleRanges": [],
                          "entityRanges": []
                        }
                      ],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400240,
                    "first_published_at_secs": null,
                    "visibility_setting": null,
                    "tweet_id": null,
                    "public_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  },
                  "content_state": {
                    "type": "string",
                    "description": "The article body as a Draft.js content-state JSON object: { blocks: [...], entityMap: [...] }. You build and edit this client-side (see the Draft.js editor-state model); it is sent as-is in the JSON request body, not as a string field.",
                    "example": "{\"blocks\":[{\"key\":\"a1b2c\",\"text\":\"Opening paragraph.\",\"type\":\"unstyled\",\"depth\":0,\"inlineStyleRanges\":[],\"entityRanges\":[]}],\"entityMap\":{}}"
                  }
                },
                "required": [
                  "id",
                  "content_state"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/article/publish": {
      "post": {
        "operationId": "article-publish",
        "summary": "Publish Article",
        "description": "Publish a draft article as the account behind your registered session, transitioning it from Draft to Published. WARNING: publishing posts a real, public announcement tweet on the account's timeline. This is not a preview or a private action, and it cannot be undone by re-editing the article: once published, the only way back is Delete Article, which unpublishes the article AND removes the announcement tweet. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/publish\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/publish\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/publish\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Publish a draft article. This posts a real, public announcement tweet.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the article was published."
                    },
                    "article": {
                      "type": "object",
                      "description": "The published article, full shape: id, rest_id, title, preview_text, lifecycle (now Published), content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs (now set), visibility_setting (now Public), tweet_id (the new announcement tweet's id), public_url (https://x.com/i/article/<rest_id>).",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "Opening paragraph.",
                    "lifecycle": "Published",
                    "content_state": {
                      "blocks": [
                        {
                          "key": "a1b2c",
                          "text": "Opening paragraph.",
                          "type": "unstyled",
                          "depth": 0,
                          "inlineStyleRanges": [],
                          "entityRanges": []
                        }
                      ],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400400,
                    "first_published_at_secs": 1786400400,
                    "visibility_setting": "Public",
                    "tweet_id": "2086650300012345678",
                    "public_url": "https://x.com/i/article/2086650228950683648"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  },
                  "audience": {
                    "type": "string",
                    "description": "Who can read the published article. Defaults to \"Everyone\" (X's own dialog default) when omitted.",
                    "example": "Everyone"
                  },
                  "reply_control": {
                    "type": "string",
                    "description": "Who can reply to the announcement tweet. Defaults to \"Everyone\" (X's own dialog default) when omitted.",
                    "example": "Everyone"
                  },
                  "caption": {
                    "type": "string",
                    "description": "Optional caption text for the announcement tweet, up to 256 characters.",
                    "example": "New post: why we rebuilt our onboarding from scratch."
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/article/unpublish": {
      "post": {
        "operationId": "article-unpublish",
        "summary": "Unpublish Article",
        "description": "Revert a Published article back to Draft, identified by its entity id. The announcement tweet the original publish posted is left in place; use Delete Article to remove it too. X server-validates this transition and returns a 422 (invalid_lifecycle) if the article is not currently Published. Requires a registered session. Billed at $0.0016 per call. Cost: $0.0016 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0016,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/unpublish\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/unpublish\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/unpublish\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Revert a published article back to Draft. The announcement tweet is left in place.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when the article was reverted to Draft."
                    },
                    "article": {
                      "type": "object",
                      "description": "The reverted article, full shape: id, rest_id, title, preview_text, lifecycle (back to Draft), content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "Opening paragraph.",
                    "lifecycle": "Draft",
                    "content_state": {
                      "blocks": [
                        {
                          "key": "a1b2c",
                          "text": "Opening paragraph.",
                          "type": "unstyled",
                          "depth": 0,
                          "inlineStyleRanges": [],
                          "entityRanges": []
                        }
                      ],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400500,
                    "first_published_at_secs": 1786400400,
                    "visibility_setting": null,
                    "tweet_id": "2086650300012345678",
                    "public_url": null
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/article/get": {
      "get": {
        "operationId": "article-get",
        "summary": "Get Article",
        "description": "Read an article's full content. Two mutually exclusive forms: id or url (the announcement tweet id or status URL) for a public, pooled read that needs no session, works for Published articles only. Or article_id (the article's own entity id, from Article Create or Article List) for an owner-only read that requires a registered session and also works for your own Drafts. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/article/get?id=2086650300012345678\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/article/get\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"id\": \"2086650300012345678\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/article/get\");\nurl.search = new URLSearchParams({ id: \"2086650300012345678\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Read an article via its announcement tweet, or your own via its entity id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Echo of the announcement tweet id that was resolved from your id/url."
                    },
                    "article": {
                      "type": "object",
                      "description": "The published article, or null if no article was found at that tweet id/URL. Full shape when present: id, rest_id, title, preview_text, lifecycle (Published), content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting (Public), tweet_id, public_url.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "id": "2086650300012345678",
                  "article": {
                    "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                    "rest_id": "2086650228950683648",
                    "title": "Why we rebuilt our onboarding from scratch",
                    "preview_text": "Opening paragraph.",
                    "lifecycle": "Published",
                    "content_state": {
                      "blocks": [
                        {
                          "key": "a1b2c",
                          "text": "Opening paragraph.",
                          "type": "unstyled",
                          "depth": 0,
                          "inlineStyleRanges": [],
                          "entityRanges": []
                        }
                      ],
                      "entityMap": []
                    },
                    "cover_media": null,
                    "media_entities": [],
                    "author": {
                      "id": "44196397",
                      "username": "elonmusk",
                      "name": "Elon Musk"
                    },
                    "created_at_secs": 1786400000,
                    "modified_at_secs": 1786400400,
                    "first_published_at_secs": 1786400400,
                    "visibility_setting": "Public",
                    "tweet_id": "2086650300012345678",
                    "public_url": "https://x.com/i/article/2086650228950683648"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "PUBLIC form. The article's announcement tweet id, or its status URL. Provide exactly one of id, url, or article_id.",
            "schema": {
              "type": "string",
              "description": "PUBLIC form. The article's announcement tweet id, or its status URL. Provide exactly one of id, url, or article_id.",
              "example": "2086650300012345678"
            },
            "example": "2086650300012345678"
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "PUBLIC form. Status URL of the article's announcement tweet, for example https://x.com/i/status/2086650300012345678. Provide exactly one of id, url, or article_id.",
            "schema": {
              "type": "string",
              "description": "PUBLIC form. Status URL of the article's announcement tweet, for example https://x.com/i/status/2086650300012345678. Provide exactly one of id, url, or article_id.",
              "example": "https://x.com/i/status/2086650300012345678"
            },
            "example": "https://x.com/i/status/2086650300012345678"
          },
          {
            "name": "article_id",
            "in": "query",
            "required": false,
            "description": "OWNER-ONLY form. The article's own entity id, from Article Create or Article List. Requires a registered session. Provide exactly one of id, url, or article_id.",
            "schema": {
              "type": "string",
              "description": "OWNER-ONLY form. The article's own entity id, from Article Create or Article List. Requires a registered session. Provide exactly one of id, url, or article_id.",
              "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
            },
            "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
          }
        ]
      }
    },
    "/twitter/article/list": {
      "get": {
        "operationId": "article-list",
        "summary": "List Articles",
        "description": "List the caller's own articles at one lifecycle at a time: Draft or Published (default Draft). X exposes no combined view across both, so call it twice, once per lifecycle, to see everything. Cursor-paginated. Requires a registered session. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/article/list?lifecycle=draft&count=20\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/article/list\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={\"lifecycle\": \"draft\", \"count\": 20},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/article/list\");\nurl.search = new URLSearchParams({ lifecycle: \"draft\", count: \"20\" }).toString();\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Paginate all pages",
            "source": "# Walk every page until the collection array comes back empty.\ncursor=\"\"\nwhile : ; do\n  resp=$(curl -s \"https://api.twitterapis.com/twitter/article/list?lifecycle=draft&cursor=$cursor\" \\\n    -H \"Authorization: Bearer $TWITTERAPIS_KEY\")\n  count=$(echo \"$resp\" | jq '.articles | length')\n  [ \"$count\" -eq 0 ] && break\n  echo \"$resp\" | jq '.articles[]'\n  cursor=$(echo \"$resp\" | jq -r '.next_cursor // \"\"')\n  [ -z \"$cursor\" ] || [ \"$cursor\" = \"null\" ] && break\ndone"
          },
          {
            "lang": "python",
            "label": "Python: Paginate all pages",
            "source": "import os\nimport requests\n\ndef paginate():\n    cursor = \"\"\n    while True:\n        resp = requests.get(\n            \"https://api.twitterapis.com/twitter/article/list\",\n            headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n            params={\"lifecycle\": \"draft\", \"cursor\": cursor},\n        )\n        resp.raise_for_status()\n        data = resp.json()\n        items = data.get(\"articles\", [])\n        if not items:\n            break\n        for item in items:\n            yield item\n        cursor = data.get(\"next_cursor\")\n        if not cursor:\n            break\n\nfor item in paginate():\n    print(item)"
          },
          {
            "lang": "js",
            "label": "JavaScript: Paginate all pages",
            "source": "const params = { lifecycle: \"draft\", cursor: \"\" };\n\nwhile (true) {\n  const url = new URL(\"https://api.twitterapis.com/twitter/article/list\");\n  url.search = new URLSearchParams(params).toString();\n  const resp = await fetch(url, {\n    headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n  });\n  const data = await resp.json();\n  const items = data.articles ?? [];\n  if (items.length === 0) break;\n  for (const item of items) console.log(item);\n  if (!data.next_cursor) break;\n  params.cursor = data.next_cursor;\n}"
          }
        ],
        "responses": {
          "200": {
            "description": "List your own articles, filtered by lifecycle (draft or published).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of articles returned in this page."
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "Opaque cursor for the next page, or null when the list ends."
                    },
                    "articles": {
                      "type": "array",
                      "description": "Articles at the requested lifecycle, for this page. Each item: id, rest_id, title, preview_text, lifecycle, content_state, cover_media, media_entities, author, created_at_secs, modified_at_secs, first_published_at_secs, visibility_setting, tweet_id, public_url.",
                      "items": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    }
                  }
                },
                "example": {
                  "count": 1,
                  "next_cursor": null,
                  "articles": [
                    {
                      "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4",
                      "rest_id": "2086650228950683648",
                      "title": "Why we rebuilt our onboarding from scratch",
                      "preview_text": "",
                      "lifecycle": "Draft",
                      "content_state": {
                        "blocks": [],
                        "entityMap": []
                      },
                      "cover_media": null,
                      "media_entities": [],
                      "author": {
                        "id": "44196397",
                        "username": "elonmusk",
                        "name": "Elon Musk"
                      },
                      "created_at_secs": 1786400000,
                      "modified_at_secs": 1786400120,
                      "first_published_at_secs": null,
                      "visibility_setting": null,
                      "tweet_id": null,
                      "public_url": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "lifecycle",
            "in": "query",
            "required": false,
            "description": "Which set of articles to list: \"draft\" or \"published\". Defaults to \"draft\".",
            "schema": {
              "type": "string",
              "description": "Which set of articles to list: \"draft\" or \"published\". Defaults to \"draft\".",
              "example": "draft"
            },
            "example": "draft"
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "Items per page. Defaults to 20; capped at 100.",
            "schema": {
              "type": "integer",
              "description": "Items per page. Defaults to 20; capped at 100.",
              "example": "20"
            },
            "example": "20"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Pagination cursor from a previous response's next_cursor.",
            "schema": {
              "type": "string",
              "description": "Pagination cursor from a previous response's next_cursor."
            }
          }
        ]
      }
    },
    "/twitter/article/delete": {
      "post": {
        "operationId": "article-delete",
        "summary": "Delete Article",
        "description": "Delete an article you own, identified by its entity id. A Draft is hard-deleted directly. A Published article is unpublished first (reverting it to Draft) and then its announcement tweet is deleted, which is what makes it stop being publicly reachable, a two-step reversal for Publish Article. Pass lifecycle and tweet_id as optional fast-path hints when you already know them (from a prior list/create response); omitted, the server resolves them itself by scanning your Draft then Published lists, costing a couple of extra round trips. Requires a registered session. Billed at $0.0008 per call. Cost: $0.0008 per call.",
        "tags": [
          "Articles"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.0008,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/article/delete\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/article/delete\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id\": \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/article/delete\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id: \"QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Delete an article. A draft is hard-deleted; a published article is unpublished, then its announcement tweet is removed too.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "Mirrors deleted."
                    },
                    "deleted": {
                      "type": "boolean",
                      "description": "True when the delete completed: the draft was hard-deleted, or the published article was unpublished and its announcement tweet removed."
                    },
                    "id": {
                      "type": "string",
                      "description": "Echo of the article id you deleted."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "deleted": true,
                  "id": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "The article's base64 entity id, returned by article/create or article/list (the id field, not rest_id).",
                    "example": "QXJ0aWNsZUVudGl0eToyMDg2NjUwMjI4OTUwNjgzNjQ4"
                  },
                  "lifecycle": {
                    "type": "string",
                    "description": "Fast-path hint: \"draft\" or \"published\". When you already know the article's lifecycle (e.g. from a prior article/list or article/create response), pass it to skip a lookup. Omit it and the server resolves it by scanning your own Draft then Published lists.",
                    "example": "draft"
                  },
                  "tweet_id": {
                    "type": "string",
                    "description": "Fast-path hint: the announcement tweet id, for a PUBLISHED article only. Omit it and the server resolves it from the article's own metadata when lifecycle resolves to published.",
                    "example": "2086650300012345678"
                  }
                },
                "required": [
                  "id"
                ]
              }
            }
          }
        }
      }
    },
    "/twitter/grok/chat": {
      "post": {
        "operationId": "grok-chat",
        "summary": "Grok Chat",
        "description": "Send a prompt to X's in-app Grok as the account behind your session and get back one complete JSON document: the answer text, the web pages Grok cited while writing it, and the searches it ran to find them. Grok reads X in real time, so it answers about posts and accounts a general-purpose model has never seen. Send a bare post URL as the message and you get a structured summary of that post instead, including what Grok reads out of its attached images. Billed at $0.0040 per answer. Cost: $0.0040 per call.",
        "tags": [
          "Grok"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0.004,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/grok/chat\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"message\": \"What are people on X saying about the WWDC keynote today?\", \"mode\": \"auto\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/grok/chat\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"message\": \"What are people on X saying about the WWDC keynote today?\", \"mode\": \"auto\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/grok/chat\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ message: \"What are people on X saying about the WWDC keynote today?\", mode: \"auto\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          },
          {
            "lang": "bash",
            "label": "cURL: Continue a conversation",
            "source": "# We store nothing, so turn 2 replays turn 1 and passes the conversation id back.\ncurl -X POST \"https://api.twitterapis.com/twitter/grok/chat\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"conversation_id\": \"2088999211077345534\",\n    \"messages\": [\n      { \"role\": \"user\", \"content\": \"What are people on X saying about the WWDC keynote today?\" },\n      { \"role\": \"assistant\", \"content\": \"Reaction is running positive on the on-device model work.\" }\n    ],\n    \"message\": \"Which developer accounts are driving that?\"\n  }'"
          },
          {
            "lang": "python",
            "label": "Python: Continue a conversation",
            "source": "import os\nimport requests\n\nKEY = os.environ[\"TWITTERAPIS_KEY\"]\nURL = \"https://api.twitterapis.com/twitter/grok/chat\"\nHEADERS = {\"Authorization\": f\"Bearer {KEY}\"}\n\nfirst = requests.post(\n    URL,\n    headers=HEADERS,\n    json={\"message\": \"What are people on X saying about the WWDC keynote today?\"},\n)\nfirst.raise_for_status()\nturn1 = first.json()\n\n# Nothing is stored on our side, so you carry the history forward yourself.\nsecond = requests.post(\n    URL,\n    headers=HEADERS,\n    json={\n        \"conversation_id\": turn1[\"conversation_id\"],\n        \"messages\": [\n            {\"role\": \"user\", \"content\": \"What are people on X saying about the WWDC keynote today?\"},\n            {\n                \"role\": \"assistant\",\n                \"content\": turn1[\"answer\"],\n                \"response_id\": turn1[\"response_id\"],\n                \"parent_response_id\": turn1[\"user_response_id\"],\n            },\n        ],\n        \"message\": \"Which developer accounts are driving that?\",\n    },\n)\nsecond.raise_for_status()\nprint(second.json()[\"answer\"])"
          },
          {
            "lang": "js",
            "label": "JavaScript: Continue a conversation",
            "source": "const URL = \"https://api.twitterapis.com/twitter/grok/chat\";\nconst headers = {\n  Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n  \"Content-Type\": \"application/json\",\n};\n\nconst first = await (\n  await fetch(URL, {\n    method: \"POST\",\n    headers,\n    body: JSON.stringify({ message: \"What are people on X saying about the WWDC keynote today?\" }),\n  })\n).json();\n\n// Nothing is stored on our side, so you carry the history forward yourself.\nconst second = await (\n  await fetch(URL, {\n    method: \"POST\",\n    headers,\n    body: JSON.stringify({\n      conversation_id: first.conversation_id,\n      messages: [\n        { role: \"user\", content: \"What are people on X saying about the WWDC keynote today?\" },\n        {\n          role: \"assistant\",\n          content: first.answer,\n          response_id: first.response_id,\n          parent_response_id: first.user_response_id,\n        },\n      ],\n      message: \"Which developer accounts are driving that?\",\n    }),\n  })\n).json();\n\nconsole.log(second.answer);"
          }
        ],
        "responses": {
          "200": {
            "description": "Ask X's Grok a question and get the answer plus the pages it cited.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "description": "True when Grok returned answer text. A call that produced no readable answer does not reach you as ok: false, it returns 422 and is not billed."
                    },
                    "conversation_id": {
                      "type": "string",
                      "description": "The conversation this turn belongs to, whether you supplied it or we opened it. Pass it back on the next call to continue. Null only if X returned no id."
                    },
                    "response_id": {
                      "type": "string",
                      "description": "The id of GROK's turn (X's agentChatItemId). Pass it back as response_id on that turn inside messages[] to thread the next request exactly."
                    },
                    "user_response_id": {
                      "type": "string",
                      "description": "The id of the turn YOU just sent (X's userChatItemId). Its counterpart to response_id when you replay history."
                    },
                    "answer": {
                      "type": "string",
                      "description": "Grok's answer as one complete string. Reasoning and tool chatter are stripped out; this is the reply a person would read."
                    },
                    "citations": {
                      "type": "object",
                      "description": "The pages Grok read while answering, each { url, domain, title, snippet }. domain is derived from url on our side; X does not send it. title is NOT always present and comes back null when X omits it, so do not filter on it. One answer can cite results from several searches: they are merged in the order they arrived and de-duplicated by url, so you get every distinct source once.",
                      "additionalProperties": true
                    },
                    "citation_count": {
                      "type": "integer",
                      "description": "Length of citations, after de-duplication. Convenient for the common case of checking whether a domain appeared at all."
                    },
                    "tool_calls": {
                      "type": "object",
                      "description": "What Grok actually ran to answer, each { id, tool, args }. The observed tool is web_search, whose args carry the query string and the number of results asked for. This is the search Grok chose, not the prompt you sent.",
                      "additionalProperties": true
                    },
                    "requested_model": {
                      "type": "string",
                      "description": "The model id we asked X for, derived from your mode: grok-4-auto, grok-3-latest, or grok-4."
                    },
                    "model": {
                      "type": "string",
                      "description": "The model that ACTUALLY answered. auto resolves on X's side, so asking for grok-4-auto commonly comes back as grok-4. Read this one when you care which model produced the text."
                    },
                    "mode": {
                      "type": "string",
                      "description": "The mode this call ran in: auto, fast, or expert. Echoed back so an unrecognised mode value is visible rather than silent."
                    }
                  }
                },
                "example": {
                  "ok": true,
                  "conversation_id": "2088999211077345534",
                  "response_id": "2089001859230978049",
                  "user_response_id": "2089001859230978048",
                  "answer": "Reaction on X is running positive on the on-device model work and negative on the pricing. The liveblog thread and several developer accounts flag the new background-execution API as the change most people expect to ship against first.",
                  "citations": [
                    {
                      "url": "https://x.com/verge/status/2089000000000000001",
                      "domain": "x.com",
                      "title": "The Verge on X",
                      "snippet": "Everything announced in the keynote, in order."
                    },
                    {
                      "url": "https://www.theverge.com/wwdc-keynote-liveblog",
                      "domain": "theverge.com",
                      "title": "WWDC keynote liveblog",
                      "snippet": "Live updates as the keynote runs."
                    },
                    {
                      "url": "https://news.ycombinator.com/item?id=41234567",
                      "domain": "news.ycombinator.com",
                      "title": null,
                      "snippet": "Developer discussion of the background-execution API."
                    }
                  ],
                  "citation_count": 3,
                  "tool_calls": [
                    {
                      "id": "5f2b8c1a-9d34-4c77-b0e2-6a1f7c3d8e90",
                      "tool": "web_search",
                      "args": {
                        "query": "WWDC keynote reaction developers",
                        "num_results": "15"
                      }
                    }
                  ],
                  "requested_model": "grok-4-auto",
                  "model": "grok-4",
                  "mode": "auto"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "message": {
                    "type": "string",
                    "description": "The prompt. A question, an instruction, or a bare post URL (https://x.com/<user>/status/<id>), which returns a summary of that post. Required unless you send messages[] whose last entry is a user turn. Maximum 20,000 characters; longer prompts are rejected with 400 before any Grok call is made, so an over-length prompt never costs you anything.",
                    "example": "What are people on X saying about the WWDC keynote today?"
                  },
                  "messages": {
                    "type": "string",
                    "description": "JSON array of prior turns, oldest first, sent in the request body. Each entry takes either { role: \"user\" | \"assistant\", content } or X's own { sender: 1 | 2, message }, where 1 is you and 2 is Grok, plus the optional response_id and parent_response_id we returned on earlier replies. Anything not explicitly marked as Grok is treated as a user turn. If you omit message, the last entry must be a user turn and becomes the prompt. Maximum 100 prior turns.",
                    "example": "[{\"role\":\"user\",\"content\":\"Who won the game?\"},{\"role\":\"assistant\",\"content\":\"The Celtics, 112-108.\"}]"
                  },
                  "mode": {
                    "type": "string",
                    "description": "auto, fast, or expert. auto lets X pick the model, fast is grok-3-latest, expert is grok-4 and thinks for longer. The raw model ids grok-3-latest and grok-4 are accepted as aliases. Anything unrecognised falls back to auto, which is also the default.",
                    "example": "auto"
                  },
                  "conversation_id": {
                    "type": "string",
                    "description": "Continue an existing conversation, using the conversation_id from an earlier reply. Omit it and we open a fresh conversation for you and return its id.",
                    "example": "2088999211077345534"
                  },
                  "image_count": {
                    "type": "integer",
                    "description": "How many images Grok may generate if the prompt calls for it. Clamped to 0 through 4; the default is 4, which is X's own. Set it to 0 for a text-only answer.",
                    "example": "4"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/twitter/grok/config": {
      "get": {
        "operationId": "grok-config",
        "summary": "Grok Config",
        "description": "Read the Grok settings for the account behind your session: whether X has enabled Grok for it, the reasons if not, and the model options it is allowed to choose between. Grok eligibility belongs to the X account rather than to us, so this runs as your session and not off our pool. Call it once before your first chat request. This call is free and is not metered. Cost: Free per call.",
        "tags": [
          "Grok"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/grok/config\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/grok/config\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/grok/config\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Check whether your account can use Grok, and which models it may pick.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "eligible": {
                      "type": "boolean",
                      "description": "True when X has Grok enabled for the account behind your session. Read it together with ineligible_reasons: false with an empty reasons array means we could not read the config, not that X refused."
                    },
                    "ineligible_reasons": {
                      "type": "object",
                      "description": "X's own reason strings, passed through unchanged because we cannot improve on X's reason for refusing its own feature. Empty when the account is eligible, and also empty in the could-not-read case above.",
                      "additionalProperties": true
                    },
                    "free_access_enabled": {
                      "type": "boolean",
                      "description": "True when X is currently granting this account Grok access without a paid tier."
                    },
                    "default_mode": {
                      "type": "string",
                      "description": "The mode X has set as this account's default, in X's own spelling, for example Normal. This is X's label, not one of the auto/fast/expert values Grok Chat takes."
                    },
                    "default_model_option_id": {
                      "type": "string",
                      "description": "The model id X defaults this account to, for example grok-4-auto."
                    },
                    "grok_version": {
                      "type": "string",
                      "description": "The Grok version string X reports for this account."
                    },
                    "modes": {
                      "type": "object",
                      "description": "The map Grok Chat's mode parameter uses: { auto: grok-4-auto, fast: grok-3-latest, expert: grok-4 }. Constant, returned here so you do not have to keep the mapping table in your own code.",
                      "additionalProperties": true
                    },
                    "model_options": {
                      "type": "object",
                      "description": "One entry per model X offers this account: id, name (Auto, Fast, Expert), description, mode (MODEL_MODE_AUTO, MODEL_MODE_FAST or MODEL_MODE_EXPERT), is_enabled, is_analyze_enabled, is_enhance_enabled. Empty when the config could not be read.",
                      "additionalProperties": true
                    }
                  }
                },
                "example": {
                  "eligible": true,
                  "ineligible_reasons": [],
                  "free_access_enabled": false,
                  "default_mode": "Normal",
                  "default_model_option_id": "grok-4-auto",
                  "grok_version": "grok-4-auto",
                  "modes": {
                    "auto": "grok-4-auto",
                    "fast": "grok-3-latest",
                    "expert": "grok-4"
                  },
                  "model_options": [
                    {
                      "id": "grok-4-auto",
                      "name": "Auto",
                      "description": "Picks the model that suits the question.",
                      "mode": "MODEL_MODE_AUTO",
                      "is_enabled": true,
                      "is_analyze_enabled": false,
                      "is_enhance_enabled": false
                    },
                    {
                      "id": "grok-3-latest",
                      "name": "Fast",
                      "description": "Answers quickly.",
                      "mode": "MODEL_MODE_FAST",
                      "is_enabled": true,
                      "is_analyze_enabled": true,
                      "is_enhance_enabled": true
                    },
                    {
                      "id": "grok-4",
                      "name": "Expert",
                      "description": "Thinks for longer before answering.",
                      "mode": "MODEL_MODE_EXPERT",
                      "is_enabled": true,
                      "is_analyze_enabled": false,
                      "is_enhance_enabled": false
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/monitor": {
      "post": {
        "operationId": "monitor-post",
        "summary": "Create Monitor",
        "description": "Start watching an X account. Every new post from that account is delivered, HMAC-signed, to your registered webhook(s) on a shared poll interval. Replies are delivered too unless you pass include_replies: false. Free: monitor creation is account administration, not a metered read. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/monitor\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"handle\": \"elonmusk\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/monitor\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"handle\": \"elonmusk\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/monitor\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ handle: \"elonmusk\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Watch an X account for new posts and push them to your webhook(s).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The new monitor's id, used in the update/delete/health routes below."
                    },
                    "handle": {
                      "type": "string",
                      "description": "The normalized (lowercased, @ stripped) handle being watched."
                    },
                    "subject": {
                      "type": "string",
                      "description": "Internal query expression for this monitor, currently always from:<handle>."
                    },
                    "kind": {
                      "type": "string",
                      "description": "Monitor type. Currently always \"account\"."
                    },
                    "status": {
                      "type": "string",
                      "description": "\"active\" or \"paused\"."
                    },
                    "webhook_ids": {
                      "type": "string",
                      "description": "The restriction set passed at create, or null for the default (deliver to all)."
                    },
                    "domain_filter": {
                      "type": "string",
                      "description": "The normalized domain filter passed at create, or null if none was set (deliver every new post)."
                    },
                    "poll_interval_ms": {
                      "type": "integer",
                      "description": "Current poll interval in milliseconds. Not yet a published SLA; subject to change."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "ISO 8601 creation timestamp."
                    },
                    "include_replies": {
                      "type": "boolean",
                      "description": "Whether replies are delivered for this monitor. True unless false was passed at create."
                    }
                  }
                },
                "example": {
                  "id": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11",
                  "handle": "elonmusk",
                  "subject": "from:elonmusk",
                  "kind": "account",
                  "status": "active",
                  "webhook_ids": null,
                  "domain_filter": null,
                  "poll_interval_ms": 120000,
                  "poll_interval_note": "NOT a published SLA yet, subject to change.",
                  "created_at": "2026-08-13T10:00:00.000Z",
                  "include_replies": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string",
                    "description": "The X username to watch, without the @.",
                    "example": "elonmusk"
                  },
                  "webhook_ids": {
                    "type": "string",
                    "description": "Array of webhook ids (from POST /twitter/webhook) to restrict delivery to. Omit to deliver to every active webhook on the account, the default.",
                    "example": "[]"
                  },
                  "domain_filter": {
                    "type": "string",
                    "description": "Optional. A bare hostname (`example.com`) or a full URL (`https://example.com/blog`) to restrict delivery to posts that link to that host or a subdomain of it. Normalized server-side: lowercased, scheme/path/query/fragment/leading www./trailing :port stripped. Omit for no filter (deliver every new post, the default). Rejected with 400 if what remains after normalization is not a valid hostname shape.",
                    "example": "example.com"
                  },
                  "include_replies": {
                    "type": "boolean",
                    "default": true,
                    "description": "Whether this monitor delivers the account's replies as well as its own posts. Defaults to true, which is what every monitor has always done. Set false to hold replies back and receive only the account's own posts; they are still polled and still advance the monitor's cursor, they are just not delivered. Must be a boolean if sent: a string or number is rejected with 400 rather than coerced.",
                    "example": false
                  }
                },
                "required": [
                  "handle"
                ]
              }
            }
          }
        }
      },
      "get": {
        "operationId": "monitor-get",
        "summary": "List Monitors",
        "description": "Returns every non-deleted monitor on your account, most recently created first. Each entry includes its id, subject, status, and delivery configuration, so you can enumerate what already exists before creating, updating, or deleting a specific monitor. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/monitor\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/monitor\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/monitor\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List every monitor on your account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "monitors": {
                      "type": "string",
                      "description": "Array of monitor objects: id, subject, kind, status, degraded, events_possibly_missed, webhook_ids, domain_filter, include_replies, created_at."
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of monitors returned."
                    }
                  }
                },
                "example": {
                  "monitors": [
                    {
                      "id": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11",
                      "subject": "from:elonmusk",
                      "kind": "account",
                      "status": "active",
                      "degraded": false,
                      "events_possibly_missed": 0,
                      "webhook_ids": null,
                      "domain_filter": null,
                      "include_replies": true,
                      "created_at": "2026-08-13T10:00:00.000Z"
                    }
                  ],
                  "count": 1
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/monitor/{id}": {
      "post": {
        "operationId": "monitor-id-post",
        "summary": "Update Monitor",
        "description": "Partial update of an existing monitor. Send status to pause or resume it, webhook_ids to change which webhooks receive its events, include_replies to turn reply delivery on or off, or any combination in the same call (applied atomically). Resuming a paused monitor re-runs the same capacity and per-account cap checks as creating a new one, since it adds load back to the shared pool. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/monitor/{id}\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"status\": \"paused\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/monitor/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"status\": \"paused\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/monitor/{id}\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ status: \"paused\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Pause, resume, or change which webhooks a monitor delivers to.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The monitor's id."
                    },
                    "subject": {
                      "type": "string",
                      "description": "The monitor's query expression, e.g. from:elonmusk."
                    },
                    "kind": {
                      "type": "string",
                      "description": "Monitor type."
                    },
                    "status": {
                      "type": "string",
                      "description": "\"active\" or \"paused\" after the update."
                    },
                    "degraded": {
                      "type": "boolean",
                      "description": "Whether the shared pool is currently serving this monitor slower than the published interval."
                    },
                    "events_possibly_missed": {
                      "type": "integer",
                      "description": "Running count of possibly-missed events, never reset by an update."
                    },
                    "webhook_ids": {
                      "type": "string",
                      "description": "The current restriction set, or null for the default (deliver to all)."
                    },
                    "domain_filter": {
                      "type": "string",
                      "description": "The current normalized domain filter after this update, or null if none is set (deliver every new post)."
                    },
                    "updated_at": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of this update."
                    },
                    "include_replies": {
                      "type": "boolean",
                      "description": "Whether replies are delivered after this update. True unless it has been set to false."
                    }
                  }
                },
                "example": {
                  "id": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11",
                  "subject": "from:elonmusk",
                  "kind": "account",
                  "status": "paused",
                  "degraded": false,
                  "events_possibly_missed": 0,
                  "webhook_ids": null,
                  "domain_filter": null,
                  "updated_at": "2026-08-13T11:00:00.000Z",
                  "include_replies": true
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "\"active\" to resume, \"paused\" to pause. Omit to leave status unchanged.",
                    "example": "paused"
                  },
                  "webhook_ids": {
                    "type": "string",
                    "description": "Array of webhook ids to restrict delivery to. Send an empty array to clear the restriction back to \"deliver to every active webhook\". Omit the field entirely to leave it unchanged.",
                    "example": "[]"
                  },
                  "domain_filter": {
                    "type": "string",
                    "description": "A bare hostname or full URL to restrict delivery to. Send null or an empty string to clear an existing filter (deliver every new post again). Omit the field entirely to leave it unchanged. Same normalization and hostname-shape validation as Create Monitor.",
                    "example": "example.com"
                  },
                  "include_replies": {
                    "type": "boolean",
                    "default": true,
                    "description": "True to deliver the account's replies as well as its own posts, false to deliver only its own posts. Omit to leave it unchanged. There is no \"clear\" value: true already is the unrestricted setting, so send true to undo a previous false. Must be a boolean, null included, or the call is rejected with 400 rather than coerced. An include_replies-only update never re-runs the capacity or per-account cap checks, since it narrows delivery without changing poll cadence.",
                    "example": false
                  }
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "monitor-id-delete",
        "summary": "Delete Monitor",
        "description": "Soft-deletes the monitor: it stops polling immediately and disappears from List Monitors, but its delivery history is retained rather than cascade-deleted. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.twitterapis.com/twitter/monitor/{id}\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.delete(\n    \"https://api.twitterapis.com/twitter/monitor/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/monitor/{id}\", {\n  method: \"DELETE\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Stop watching an account and remove the monitor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "description": "True on success."
                    },
                    "id": {
                      "type": "string",
                      "description": "The deleted monitor's id."
                    }
                  }
                },
                "example": {
                  "deleted": true,
                  "id": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/monitor/{id}/health": {
      "get": {
        "operationId": "monitor-id-health",
        "summary": "Monitor Health",
        "description": "Returns a single monitor's current status, degradation flag, and cursor position, for building your own health dashboard. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/monitor/{id}/health\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/monitor/{id}/health\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/monitor/{id}/health\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Check one monitor's poll status and last-seen tweet id.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The monitor's id."
                    },
                    "status": {
                      "type": "string",
                      "description": "\"active\" or \"paused\"."
                    },
                    "degraded": {
                      "type": "boolean",
                      "description": "Whether the shared pool is currently serving this monitor slower than the published interval."
                    },
                    "poll_interval_ms": {
                      "type": "integer",
                      "description": "Current poll interval in milliseconds."
                    },
                    "events_possibly_missed": {
                      "type": "integer",
                      "description": "Running count of possibly-missed events."
                    },
                    "last_tweet_id": {
                      "type": "string",
                      "description": "The most recent tweet id this monitor has delivered, or null before its first poll."
                    },
                    "last_poll_at": {
                      "type": "string",
                      "description": "ISO 8601 timestamp of the most recent poll, or null before the first one."
                    }
                  }
                },
                "example": {
                  "id": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11",
                  "status": "active",
                  "degraded": false,
                  "poll_interval_ms": 120000,
                  "events_possibly_missed": 0,
                  "last_tweet_id": "1899999999999999999",
                  "last_poll_at": "2026-08-13T11:58:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/monitor/health": {
      "get": {
        "operationId": "monitor-health",
        "summary": "Account Monitor Health",
        "description": "Returns a single-call summary of your entire monitoring setup: overall status, how many of your monitors are active vs paused, and how many delivery attempts in the last 24 hours were pending, delivered, or failed. Distinct from Monitor Health above, which reports one monitor's cursor state, not your whole account's. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/monitor/health\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/monitor/health\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/monitor/health\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Account-wide monitoring rollup: service status, active/paused counts, 24h delivery outcomes, in one call.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "\"operational\", or \"degraded\" if any of your ACTIVE monitors is currently being served slower than the published poll interval. A degraded paused monitor never flips this, since nothing is polling it."
                    },
                    "monitors": {
                      "type": "string",
                      "description": "Counts across every non-deleted monitor you own: active, paused, and total."
                    },
                    "deliveries_24h": {
                      "type": "string",
                      "description": "Counts across every delivery attempt created in the last 24 hours: pending (still queued or retrying), delivered (succeeded), and failed (dead-lettered after retries were exhausted)."
                    }
                  }
                },
                "example": {
                  "status": "operational",
                  "monitors": {
                    "active": 3,
                    "paused": 1,
                    "total": 4
                  },
                  "deliveries_24h": {
                    "pending": 2,
                    "delivered": 150,
                    "failed": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/monitor/deliveries": {
      "get": {
        "operationId": "monitor-deliveries",
        "summary": "Monitor Deliveries",
        "description": "Returns your most recent monitor delivery events, most recent first, each carrying the actual measured lag: detected_lag_ms is X's own post timestamp subtracted from the moment our scheduler enqueued the delivery (i.e. real detection latency, bound by the current poll interval), and delivery_lag_ms is the separate queue-to-webhook-POST time. Either can be null for an older event whose payload predates this field. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/monitor/deliveries\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/monitor/deliveries\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/monitor/deliveries\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Recent delivery events across every monitor, with real detection and delivery latency.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deliveries": {
                      "type": "string",
                      "description": "Array of delivery events: id, monitor_id, tweet_id, status, tweet_created_at, detected_at, delivered_at, detected_lag_ms, delivery_lag_ms, total_lag_ms."
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of events returned."
                    }
                  }
                },
                "example": {
                  "deliveries": [
                    {
                      "id": "79a94efd-8b6c-46f7-afa5-1fecdf1250a1",
                      "monitor_id": "bd964ae0-7763-4dd6-9295-233d9badf6f9",
                      "tweet_id": "2087910515246784773",
                      "status": "delivered",
                      "tweet_created_at": "Thu Aug 13 14:33:52 +0000 2026",
                      "detected_at": "2026-08-13T14:34:25.984Z",
                      "delivered_at": "2026-08-13T14:34:29.580Z",
                      "detected_lag_ms": 33984,
                      "delivery_lag_ms": 3596,
                      "total_lag_ms": 37580
                    }
                  ],
                  "count": 1
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Max events to return, 1-200. Defaults to 50.",
            "schema": {
              "type": "integer",
              "description": "Max events to return, 1-200. Defaults to 50.",
              "example": "50"
            },
            "example": "50"
          }
        ]
      }
    },
    "/oapi/x_user_stream/add_user_to_monitor_tweet": {
      "post": {
        "operationId": "oapi-x-user-stream-add-user-to-monitor-tweet",
        "summary": "Compat: Add User to Tweet Monitoring",
        "description": "An x_user_stream-shaped request/response envelope, translated onto the exact same underlying monitor system as POST /twitter/monitor -- not a second capability, one system with two request shapes in front of it. Migrating an integration already built against that shape? Point it at this path instead of rewriting it against /twitter/monitor. Free: account administration, not a metered read, billed identically to /twitter/monitor. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/oapi/x_user_stream/add_user_to_monitor_tweet\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"x_user_name\": \"elonmusk\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/oapi/x_user_stream/add_user_to_monitor_tweet\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"x_user_name\": \"elonmusk\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/oapi/x_user_stream/add_user_to_monitor_tweet\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ x_user_name: \"elonmusk\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "x_user_stream-shaped drop-in for Create Monitor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "\"success\" or \"error\"."
                    },
                    "msg": {
                      "type": "string",
                      "description": "Human-readable result, e.g. \"User added to tweet monitoring.\""
                    }
                  }
                },
                "example": {
                  "status": "success",
                  "msg": "User added to tweet monitoring."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "x_user_name": {
                    "type": "string",
                    "description": "The X username to watch, without the @.",
                    "example": "elonmusk"
                  }
                },
                "required": [
                  "x_user_name"
                ]
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://api.twitterapis.com"
        }
      ]
    },
    "/oapi/x_user_stream/remove_user_to_monitor_tweet": {
      "post": {
        "operationId": "oapi-x-user-stream-remove-user-to-monitor-tweet",
        "summary": "Compat: Remove User from Tweet Monitoring",
        "description": "An x_user_stream-shaped request/response envelope for removing a monitored user, translated onto DELETE /twitter/monitor/{id}. id_for_user is exactly our monitor id -- get it from get_user_to_monitor_tweet, i.e. it is an opaque handle from that list response, which is what our id already is. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/oapi/x_user_stream/remove_user_to_monitor_tweet\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id_for_user\": \"b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/oapi/x_user_stream/remove_user_to_monitor_tweet\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"id_for_user\": \"b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/oapi/x_user_stream/remove_user_to_monitor_tweet\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ id_for_user: \"b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "x_user_stream-shaped drop-in for Delete Monitor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "\"success\" or \"error\"."
                    },
                    "msg": {
                      "type": "string",
                      "description": "Human-readable result, e.g. \"User removed from tweet monitoring.\""
                    }
                  }
                },
                "example": {
                  "status": "success",
                  "msg": "User removed from tweet monitoring."
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id_for_user": {
                    "type": "string",
                    "description": "The monitor id, from GET /oapi/x_user_stream/get_user_to_monitor_tweet.",
                    "example": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11"
                  }
                },
                "required": [
                  "id_for_user"
                ]
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://api.twitterapis.com"
        }
      ]
    },
    "/oapi/x_user_stream/get_user_to_monitor_tweet": {
      "get": {
        "operationId": "oapi-x-user-stream-get-user-to-monitor-tweet",
        "summary": "Compat: List Tweet-Monitored Users",
        "description": "An x_user_stream-shaped response envelope for listing monitored users, backed by the same monitor rows GET /twitter/monitor returns. Honest field mapping, not fabricated: our monitors table stores no numeric Twitter user id and no separate display name, so x_user_id is always null and x_user_name/x_user_screen_name both carry the handle we actually store. is_monitor_profile (profile-change monitoring) is not a capability this API has -- always 0, never reported as on. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/oapi/x_user_stream/get_user_to_monitor_tweet\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/oapi/x_user_stream/get_user_to_monitor_tweet\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/oapi/x_user_stream/get_user_to_monitor_tweet\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "x_user_stream-shaped drop-in for List Monitors.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "description": "\"success\" or \"error\"."
                    },
                    "msg": {
                      "type": "string",
                      "description": "Human-readable count summary, e.g. \"1 monitored user(s).\""
                    },
                    "data": {
                      "type": "string",
                      "description": "Array of monitored-user objects: id_for_user, x_user_id (always null), x_user_name, x_user_screen_name, is_monitor_tweet, is_monitor_profile (always 0), monitor_tweet_config_status, monitor_profile_config_status, created_at."
                    }
                  }
                },
                "example": {
                  "status": "success",
                  "msg": "1 monitored user(s).",
                  "data": [
                    {
                      "id_for_user": "b6f2c1a4-9e3d-4c11-8a2f-7d5e6c9b0a11",
                      "x_user_id": null,
                      "x_user_name": "elonmusk",
                      "x_user_screen_name": "elonmusk",
                      "is_monitor_tweet": 1,
                      "is_monitor_profile": 0,
                      "monitor_tweet_config_status": 1,
                      "monitor_profile_config_status": 0,
                      "created_at": "2026-08-13T10:00:00.000Z"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      },
      "servers": [
        {
          "url": "https://api.twitterapis.com"
        }
      ]
    },
    "/twitter/webhook": {
      "post": {
        "operationId": "webhook-post",
        "summary": "Create Webhook",
        "description": "Register your HTTPS endpoint to receive signed monitor events. The signing secret is returned exactly once in this response; store it immediately, it cannot be retrieved again. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/webhook\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"url\": \"https://example.com/webhooks/twitterapis\"}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/webhook\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={\"url\": \"https://example.com/webhooks/twitterapis\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/webhook\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({ url: \"https://example.com/webhooks/twitterapis\" }),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Register a URL to receive monitor events.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The new webhook's id."
                    },
                    "url": {
                      "type": "string",
                      "description": "The registered delivery URL."
                    },
                    "status": {
                      "type": "string",
                      "description": "\"active\" (delivers) or \"disabled\" (a 410 Gone response from your endpoint sets this; re-register to reactivate)."
                    },
                    "secret": {
                      "type": "string",
                      "description": "The HMAC signing secret, shown ONLY in this response. Use it to verify the X-TwitterAPIs-Signature header on every delivery."
                    },
                    "created_at": {
                      "type": "string",
                      "description": "ISO 8601 creation timestamp."
                    }
                  }
                },
                "example": {
                  "id": "e4a1f9c2-3b7d-4a88-9f1e-2c6d8b4a5e10",
                  "url": "https://example.com/webhooks/twitterapis",
                  "status": "active",
                  "secret": "<your-webhook-signing-secret>",
                  "created_at": "2026-08-13T10:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "Your https delivery endpoint. Private, loopback, link-local, and metadata IPs are refused, re-checked at every delivery, not just at creation.",
                    "example": "https://example.com/webhooks/twitterapis"
                  }
                },
                "required": [
                  "url"
                ]
              }
            }
          }
        }
      },
      "get": {
        "operationId": "webhook-get",
        "summary": "List Webhooks",
        "description": "Returns every non-deleted webhook on your account. Never returns the signing secret; that is shown once, at creation. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl \"https://api.twitterapis.com/twitter/webhook\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.get(\n    \"https://api.twitterapis.com/twitter/webhook\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    params={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const url = new URL(\"https://api.twitterapis.com/twitter/webhook\");\nconst resp = await fetch(url, {\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "List every webhook on your account.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "webhooks": {
                      "type": "string",
                      "description": "Array of webhook objects: id, url, status, created_at."
                    },
                    "count": {
                      "type": "integer",
                      "description": "Number of webhooks returned."
                    }
                  }
                },
                "example": {
                  "webhooks": [
                    {
                      "id": "e4a1f9c2-3b7d-4a88-9f1e-2c6d8b4a5e10",
                      "url": "https://example.com/webhooks/twitterapis",
                      "status": "active",
                      "created_at": "2026-08-13T10:00:00.000Z"
                    }
                  ],
                  "count": 1
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/webhook/{id}/test": {
      "post": {
        "operationId": "webhook-id-test",
        "summary": "Test Webhook",
        "description": "Sends a single HMAC-signed test event to this webhook's URL right now and returns the outcome synchronously. Unlike a real monitor event, a test send is never queued, retried, or dead-lettered: it is a one-shot diagnostic so you can confirm your endpoint and signature verification both work before relying on the webhook. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X POST \"https://api.twitterapis.com/twitter/webhook/{id}/test\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{}'"
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.post(\n    \"https://api.twitterapis.com/twitter/webhook/{id}/test\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n    json={},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/webhook/{id}/test\", {\n  method: \"POST\",\n  headers: {\n    Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}`,\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({}),\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Fire one real signed test delivery and see the result immediately.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "The webhook's id."
                    },
                    "delivered": {
                      "type": "boolean",
                      "description": "True if your endpoint returned a 2xx within the delivery timeout."
                    },
                    "status_code": {
                      "type": "integer",
                      "description": "The HTTP status your endpoint returned, or null if the request failed before a response was received (timeout, connection refused, DNS failure, or an egress-safety refusal)."
                    },
                    "error": {
                      "type": "string",
                      "description": "Human-readable failure reason when delivered is false, or null on success."
                    }
                  }
                },
                "example": {
                  "id": "e4a1f9c2-3b7d-4a88-9f1e-2c6d8b4a5e10",
                  "delivered": true,
                  "status_code": 200,
                  "error": null
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "forbidden",
                  "message": "The acting account is not authorized for this write action, or has no logged-in session."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    },
    "/twitter/webhook/{id}": {
      "delete": {
        "operationId": "webhook-id",
        "summary": "Delete Webhook",
        "description": "Soft-deletes the webhook: it stops receiving deliveries immediately and disappears from List Webhooks, but delivery history referencing it is retained rather than cascade-deleted. Cost: Free per call.",
        "tags": [
          "Monitoring"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-cost-usd": 0,
        "x-codeSamples": [
          {
            "lang": "bash",
            "label": "cURL",
            "source": "curl -X DELETE \"https://api.twitterapis.com/twitter/webhook/{id}\" \\\n  -H \"Authorization: Bearer $TWITTERAPIS_KEY\""
          },
          {
            "lang": "python",
            "label": "Python",
            "source": "import os\nimport requests\n\nresp = requests.delete(\n    \"https://api.twitterapis.com/twitter/webhook/{id}\",\n    headers={\"Authorization\": f\"Bearer {os.environ['TWITTERAPIS_KEY']}\"},\n)\nresp.raise_for_status()\ndata = resp.json()\nprint(data)"
          },
          {
            "lang": "js",
            "label": "JavaScript",
            "source": "const resp = await fetch(\"https://api.twitterapis.com/twitter/webhook/{id}\", {\n  method: \"DELETE\",\n  headers: { Authorization: `Bearer ${process.env.TWITTERAPIS_KEY}` },\n});\nconst data = await resp.json();\nconsole.log(data);"
          }
        ],
        "responses": {
          "200": {
            "description": "Remove a webhook.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "deleted": {
                      "type": "boolean",
                      "description": "True on success."
                    },
                    "id": {
                      "type": "string",
                      "description": "The deleted webhook's id."
                    }
                  }
                },
                "example": {
                  "deleted": true,
                  "id": "e4a1f9c2-3b7d-4a88-9f1e-2c6d8b4a5e10"
                }
              }
            }
          },
          "400": {
            "description": "Bad request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "bad_request",
                  "message": "Missing or malformed parameter. Fix the request before retrying."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "unauthorized",
                  "message": "The API key is missing, malformed, or revoked. Check the Authorization header."
                }
              }
            }
          },
          "402": {
            "description": "Insufficient credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "insufficient_credits",
                  "message": "Your balance is exhausted. Top up your credits to continue."
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "not_found",
                  "message": "The resource does not exist, for example a deleted tweet or a private account."
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "rate_limited",
                  "message": "Too many requests. Back off and retry with exponential backoff."
                }
              }
            }
          },
          "5XX": {
            "description": "Server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                },
                "example": {
                  "error": "server_error",
                  "message": "Something failed on our side. Retry with backoff; if it persists, contact support."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Tweet": {
        "type": "object",
        "description": "A single tweet with its author and engagement counts.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Numeric tweet ID as a string (avoids JS number precision loss)."
          },
          "text": {
            "type": "string",
            "description": "Full tweet text, including expanded URLs."
          },
          "created_at": {
            "type": "string",
            "description": "Tweet creation timestamp in Twitter date format."
          },
          "author": {
            "allOf": [
              {
                "$ref": "#/components/schemas/User"
              }
            ],
            "description": "The account that posted the tweet."
          },
          "favorite_count": {
            "type": "integer",
            "description": "Number of likes (favorites) at fetch time."
          },
          "retweet_count": {
            "type": "integer",
            "description": "Number of retweets at fetch time."
          },
          "reply_count": {
            "type": "integer",
            "description": "Number of replies at fetch time."
          },
          "quote_count": {
            "type": "integer",
            "description": "Number of quote tweets at fetch time."
          },
          "bookmark_count": {
            "type": "integer",
            "description": "Number of bookmarks at fetch time."
          },
          "view_count": {
            "type": "integer",
            "nullable": true,
            "description": "Number of views (impressions). May be null on older tweets posted before public view counts existed."
          },
          "url": {
            "type": "string",
            "description": "Canonical x.com status URL."
          },
          "lang": {
            "type": "string",
            "description": "BCP-47 language code Twitter detected."
          },
          "is_retweet": {
            "type": "boolean",
            "description": "True when the tweet is a retweet."
          },
          "is_quote": {
            "type": "boolean",
            "description": "True when the tweet quotes another tweet."
          },
          "is_reply": {
            "type": "boolean",
            "description": "True when the tweet is a reply to another tweet."
          },
          "source": {
            "type": "string",
            "nullable": true,
            "description": "Posting client/source label; frequently null."
          },
          "conversation_id": {
            "type": "string",
            "description": "ID of the root tweet of the conversation thread this tweet belongs to."
          },
          "in_reply_to_status_id": {
            "type": "string",
            "nullable": true,
            "description": "ID of the tweet being replied to; null when the tweet is not a reply."
          },
          "in_reply_to_user_id": {
            "type": "string",
            "nullable": true,
            "description": "Numeric ID of the user being replied to; null when not a reply."
          },
          "in_reply_to_username": {
            "type": "string",
            "nullable": true,
            "description": "Handle of the user being replied to; null when not a reply."
          },
          "display_text_range": {
            "type": "array",
            "nullable": true,
            "description": "The UTF-16 character span [start, end) of the display text inside text. It marks the region a client should render, leaving out the leading @mentions on a reply and the trailing t.co link of attached media or a quoted tweet. Always a pair, for example [0, 144] on a plain tweet and [22, 285] on a reply. Null when X sends no range, or sends one whose members are not finite numbers, so a partial range is never passed off as a complete one.",
            "items": {
              "type": "integer",
              "description": "A UTF-16 character offset into text."
            }
          },
          "is_limited_reply": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether replying to this tweet is restricted. True when X names a reply limitation, false when X names a limitation that is not about replies, and null when X names no limitation at all. Null is what every tweet sampled so far returns. The flag is relative to the account that read the tweet, and these are pooled reads served by a rotating pool account, so a value here describes that account and not yours. It is a different question from the author's own who-can-reply setting, which this field does not report."
          },
          "entities": {
            "type": "object",
            "description": "Parsed tweet entities. Always present; the arrays are empty when the tweet has none.",
            "properties": {
              "hashtags": {
                "type": "array",
                "description": "Hashtag entities in the tweet text.",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "The hashtag text without the leading #."
                    },
                    "indices": {
                      "type": "array",
                      "description": "Start/end character offsets in the tweet text.",
                      "items": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "symbols": {
                "type": "array",
                "description": "Cashtag entities ($TSLA-style) in the tweet text.",
                "items": {
                  "type": "object",
                  "properties": {
                    "text": {
                      "type": "string",
                      "description": "The cashtag text without the leading $."
                    },
                    "indices": {
                      "type": "array",
                      "description": "Start/end character offsets in the tweet text.",
                      "items": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "timestamps": {
                "type": "array",
                "description": "Date/time entities X extracts from the tweet text. Forwarded verbatim from X rather than remapped, so the member shape is whatever X sends and may gain fields without notice. Treat it as opaque unless you have verified the shape yourself.",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                }
              },
              "urls": {
                "type": "array",
                "description": "Link entities in the tweet text.",
                "items": {
                  "type": "object",
                  "properties": {
                    "url": {
                      "type": "string",
                      "description": "The t.co short URL as it appears in the text."
                    },
                    "expanded_url": {
                      "type": "string",
                      "description": "The resolved destination URL."
                    },
                    "display_url": {
                      "type": "string",
                      "description": "The human-readable display URL."
                    },
                    "indices": {
                      "type": "array",
                      "description": "Start/end character offsets in the tweet text.",
                      "items": {
                        "type": "integer"
                      }
                    }
                  }
                }
              },
              "user_mentions": {
                "type": "array",
                "description": "@-mention entities in the tweet text.",
                "items": {
                  "type": "object",
                  "properties": {
                    "id_str": {
                      "type": "string",
                      "description": "Numeric ID of the mentioned user as a string."
                    },
                    "screen_name": {
                      "type": "string",
                      "description": "Handle of the mentioned user."
                    },
                    "name": {
                      "type": "string",
                      "description": "Display name of the mentioned user."
                    },
                    "indices": {
                      "type": "array",
                      "description": "Start/end character offsets in the tweet text.",
                      "items": {
                        "type": "integer"
                      }
                    }
                  }
                }
              }
            }
          },
          "retweeted_tweet": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Tweet"
              }
            ],
            "description": "The original tweet, present only when is_retweet is true."
          },
          "quoted_tweet": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Tweet"
              }
            ],
            "description": "The quoted tweet embedded one level deep, present only when is_quote is true. The nested tweet omits its own retweeted_tweet/quoted_tweet so nesting is bounded to one level."
          },
          "media": {
            "type": "array",
            "description": "Media attachments, top-level for convenience. Same content and item shape as extended_entities.media below (the live API returns media in both places); present only when the tweet has media, omitted for text-only tweets.",
            "items": {
              "$ref": "#/components/schemas/Media"
            }
          },
          "extended_entities": {
            "type": "object",
            "description": "Media attached to the tweet, in the standard Twitter shape. Present only when the tweet has media; omitted for text-only tweets.",
            "properties": {
              "media": {
                "type": "array",
                "description": "Media attachments. Photos have no video_info; videos and GIFs carry video_info.variants.",
                "items": {
                  "$ref": "#/components/schemas/Media"
                }
              }
            }
          }
        }
      },
      "Media": {
        "type": "object",
        "description": "A single media attachment (photo, video, or GIF). Appears both as Tweet.media (top-level) and Tweet.extended_entities.media -- the live API returns the identical array in both places.",
        "properties": {
          "type": {
            "type": "string",
            "description": "Media type: \"photo\", \"video\", or \"animated_gif\"."
          },
          "media_url_https": {
            "type": "string",
            "nullable": true,
            "description": "Thumbnail/still image URL (normally twimg-hosted). Validate the host before fetching."
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "The t.co display URL for the media in the tweet text."
          },
          "ext_alt_text": {
            "type": "string",
            "description": "Author-supplied alt text, when present."
          },
          "video_info": {
            "type": "object",
            "description": "Present for \"video\" and \"animated_gif\". Pick the highest-bitrate video/mp4 variant for playback.",
            "properties": {
              "duration_millis": {
                "type": "integer",
                "description": "Clip duration in milliseconds."
              },
              "variants": {
                "type": "array",
                "description": "Playable renditions (an HLS manifest plus one or more mp4 bitrates).",
                "items": {
                  "type": "object",
                  "properties": {
                    "content_type": {
                      "type": "string",
                      "description": "MIME type, e.g. \"video/mp4\" or \"application/x-mpegURL\"."
                    },
                    "url": {
                      "type": "string",
                      "description": "Rendition URL (normally twimg-hosted). Validate the host before fetching."
                    },
                    "bitrate": {
                      "type": "integer",
                      "description": "Bitrate in bps; present on mp4 variants only."
                    }
                  }
                }
              }
            }
          }
        }
      },
      "User": {
        "type": "object",
        "description": "A Twitter/X user profile.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Numeric user ID as a string."
          },
          "username": {
            "type": "string",
            "description": "Handle without the leading @."
          },
          "name": {
            "type": "string",
            "description": "Display name."
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the account is legacy-verified."
          },
          "is_blue_verified": {
            "type": "boolean",
            "description": "Whether the account carries the Verified (Blue) badge."
          },
          "verified_type": {
            "type": "string",
            "nullable": true,
            "description": "Verification type, for example Business or Government, when applicable; null otherwise."
          },
          "followers_count": {
            "type": "integer",
            "description": "Follower count."
          },
          "following_count": {
            "type": "integer",
            "description": "Following count."
          },
          "tweet_count": {
            "type": "integer",
            "description": "Number of tweets the account has posted."
          },
          "favourites_count": {
            "type": "integer",
            "description": "Number of tweets the account has liked."
          },
          "media_count": {
            "type": "integer",
            "description": "Number of media items the account has posted."
          },
          "description": {
            "type": "string",
            "description": "Profile bio text."
          },
          "location": {
            "type": "string",
            "description": "Self-reported location."
          },
          "url": {
            "type": "string",
            "description": "Linked website URL from the profile, when set."
          },
          "created_at": {
            "type": "string",
            "description": "Account creation timestamp in Twitter date format."
          },
          "profile_image_url": {
            "type": "string",
            "description": "Avatar image URL."
          },
          "cover_picture": {
            "type": "string",
            "description": "Profile banner/cover image URL, when set."
          },
          "listed_count": {
            "type": "integer",
            "nullable": true,
            "description": "Number of public lists the account appears on."
          },
          "can_dm": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account can receive a direct message from the caller's session."
          },
          "has_custom_timelines": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account has created custom timelines."
          },
          "is_translator": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account is a Twitter/X translator."
          },
          "possibly_sensitive": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account is flagged as possibly posting sensitive media."
          },
          "default_profile": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the account still uses the default profile theme."
          },
          "default_profile_image": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the account still uses the default avatar."
          },
          "professional_type": {
            "type": "string",
            "nullable": true,
            "description": "Professional account type when set, for example \"Creator\" or \"Business\"; null otherwise."
          },
          "profile_bio": {
            "type": "object",
            "nullable": true,
            "description": "Structured bio with entity ranges, when present.",
            "properties": {
              "description": {
                "type": "string",
                "nullable": true,
                "description": "The bio text."
              },
              "entities": {
                "type": "object",
                "nullable": true,
                "additionalProperties": true,
                "description": "Mention/URL entity ranges within the bio, when present."
              }
            }
          },
          "affiliate_label": {
            "type": "object",
            "nullable": true,
            "description": "Parent-organization/affiliate badge shown on the profile, when present.",
            "properties": {
              "description": {
                "type": "string",
                "nullable": true,
                "description": "The affiliate/parent-org label text."
              },
              "badge_url": {
                "type": "string",
                "nullable": true,
                "description": "Badge image URL."
              },
              "url": {
                "type": "string",
                "nullable": true,
                "description": "Link the badge points to."
              }
            }
          },
          "pinned_tweet_ids": {
            "type": "array",
            "description": "Numeric IDs (as strings) of the account's pinned tweet(s); empty array when the account has none pinned or when a trimmed user object omits the block.",
            "items": {
              "type": "string",
              "description": "A pinned tweet ID as a string."
            }
          },
          "protected": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account is protected (locked); null on a trimmed user object that carries no protected flag."
          },
          "type": {
            "type": "string",
            "nullable": true,
            "description": "The user result __typename, for example \"User\" or \"UserUnavailable\"; null when absent."
          },
          "is_automated": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the profile carries X's automated-account label, which is how an account declares itself a bot. Null when no such label is on the profile. This field is never set to false by inference, so null means only that X did not label the account, never that a human runs it. Null on every account sampled so far, including accounts that are plainly automated."
          },
          "automated_by": {
            "type": "string",
            "nullable": true,
            "description": "Handle of the account that manages this automated account, read from the link on the automated label. Null unless is_automated is true and that label carries a single-segment x.com or twitter.com profile link. Null on every account sampled so far."
          },
          "unavailable": {
            "type": "boolean",
            "nullable": true,
            "description": "True when X reports the account as unavailable, for example suspended or withheld. False when X returns an ordinary account result. Null on a trimmed user object that reports no account type at all. It is derived from the same value as type, so the two can never disagree: a type of UserUnavailable always gives true."
          },
          "unavailable_message": {
            "type": "string",
            "nullable": true,
            "description": "The message X returns explaining why the account is unavailable, for example the text shown in place of the profile. Null when the account is available or when X sends no message."
          },
          "unavailable_reason": {
            "type": "string",
            "nullable": true,
            "description": "The short reason code X returns for an unavailable account, for example Suspended. Null when the account is available or when X sends no reason."
          },
          "withheld_in_countries": {
            "type": "array",
            "nullable": true,
            "description": "ISO country codes in which X withholds this account. The empty array and null mean different things and the difference is legally relevant if you republish profiles: an empty array is X stating the account is withheld nowhere, while null is X not telling us. Do not read null as \"not withheld\". Null on every account today, because the block this is read from is one X no longer sends; the read is kept so the field fills in on its own if X restores it.",
            "items": {
              "type": "string",
              "description": "An ISO country code, for example DE."
            }
          }
        }
      },
      "Trend": {
        "type": "object",
        "description": "A single trending topic from X's trends list.",
        "properties": {
          "name": {
            "type": "string",
            "description": "The trend text, for example a hashtag or phrase."
          },
          "url": {
            "type": "string",
            "description": "x.com search URL for the trend."
          },
          "query": {
            "type": "string",
            "description": "URL-encoded search query for the trend."
          },
          "promoted_content": {
            "nullable": true,
            "description": "Promotion metadata when the trend is a promoted/paid placement; null for organic trends."
          },
          "tweet_volume": {
            "type": "integer",
            "nullable": true,
            "description": "Approximate number of tweets in the trend over the trailing window; null when X does not report a volume."
          },
          "is_hashtag": {
            "type": "boolean",
            "description": "Whether the trend is a hashtag (its name starts with #). Derived from the trend name when X sends no literal flag."
          },
          "rank": {
            "type": "integer",
            "description": "1-based position of the trend in X's trending-rank order, assigned before any count truncation."
          },
          "meta_description": {
            "type": "string",
            "nullable": true,
            "description": "The context line X shows under a trend, for example \"Trending in United States\" or \"12.4K posts\". Null on every trend today. Trends are read from X's REST trends/place.json, whose trend object carries no context string, so there is nothing to return; the field fills in on its own the day that changes. It is deliberately not synthesised from tweet_volume, because a line written here and presented as X's would be a fabrication."
          }
        }
      },
      "TrendServedLocation": {
        "type": "object",
        "description": "The location a trends response was actually served for, echoed back in the trends envelope so the caller knows which place the trends belong to.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable location name, for example \"Worldwide\" or \"United States\"."
          },
          "woeid": {
            "type": "integer",
            "description": "The Yahoo! Where On Earth ID for the location; pass it back as the woeid parameter to re-request the same place."
          }
        }
      },
      "TrendLocation": {
        "type": "object",
        "description": "A place trends are available for, from the trends/locations directory. Pass its woeid to the trends endpoint to read that location's trends.",
        "properties": {
          "name": {
            "type": "string",
            "description": "Human-readable location name, for example \"Worldwide\", \"United States\", or a city name."
          },
          "woeid": {
            "type": "integer",
            "description": "The Yahoo! Where On Earth ID for the location; pass it as the woeid parameter to the trends endpoint."
          },
          "country": {
            "type": "string",
            "description": "Country name the location belongs to; empty string for supernames like Worldwide."
          },
          "countryCode": {
            "type": "string",
            "nullable": true,
            "description": "DEPRECATED camelCase alias of country_code, kept for a deprecation window. Prefer country_code (snake_case is our canonical convention). ISO country code for the location; null for supernames like Worldwide and for locations X reports no code for."
          },
          "country_code": {
            "type": "string",
            "nullable": true,
            "description": "ISO country code for the location; null for supernames like Worldwide and for locations X reports no code for. Canonical snake_case field (carries the same value as the deprecated camelCase countryCode)."
          },
          "parentid": {
            "type": "integer",
            "description": "WOEID of the parent location (0 for the top-level Worldwide supername)."
          },
          "placeType": {
            "type": "object",
            "description": "DEPRECATED camelCase alias of place_type, kept for a deprecation window. Prefer place_type. The location's place-type classification.",
            "properties": {
              "code": {
                "type": "integer",
                "description": "Numeric place-type code (for example 19 for a supername, 12 for a country, 7 for a town)."
              },
              "name": {
                "type": "string",
                "description": "Human-readable place-type name, for example \"Supername\", \"Country\", or \"Town\"."
              }
            }
          },
          "place_type": {
            "type": "object",
            "description": "The location's place-type classification. Canonical snake_case field (carries the same value as the deprecated camelCase placeType).",
            "properties": {
              "code": {
                "type": "integer",
                "description": "Numeric place-type code (for example 19 for a supername, 12 for a country, 7 for a town)."
              },
              "name": {
                "type": "string",
                "description": "Human-readable place-type name, for example \"Supername\", \"Country\", or \"Town\"."
              }
            }
          },
          "url": {
            "type": "string",
            "description": "The where.yahooapis.com reference URL X returns for the location."
          }
        }
      },
      "About": {
        "type": "object",
        "description": "A profile's full About object: identity, bio, location, linked website, verification and identity-verification flags, the professional account type and categories, follower/following counts, avatar, the account-creation date, and the \"About this account\" transparency panel (account country, how the account was created, username-change history).",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true,
            "description": "Numeric user ID as a string."
          },
          "username": {
            "type": "string",
            "nullable": true,
            "description": "Handle without the leading @."
          },
          "name": {
            "type": "string",
            "nullable": true,
            "description": "Display name."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "Profile bio text."
          },
          "location": {
            "type": "string",
            "nullable": true,
            "description": "Self-reported location."
          },
          "url": {
            "type": "string",
            "nullable": true,
            "description": "Linked website URL, when set."
          },
          "is_blue_verified": {
            "type": "boolean",
            "description": "Whether the account carries the Verified (Blue) badge."
          },
          "verified": {
            "type": "boolean",
            "description": "Whether the account is legacy-verified."
          },
          "verified_type": {
            "type": "string",
            "nullable": true,
            "description": "Verification type, for example Business or Government, when applicable; null otherwise."
          },
          "professional_type": {
            "type": "string",
            "nullable": true,
            "description": "Professional account type, for example \"Creator\" or \"Business\", when the account publishes one; null otherwise."
          },
          "professional_categories": {
            "type": "array",
            "description": "Professional category names the account has published (populated only for Professional/Business accounts; empty array otherwise).",
            "items": {
              "type": "string",
              "description": "A human-readable category name, for example \"Software Company\"."
            }
          },
          "followers_count": {
            "type": "integer",
            "nullable": true,
            "description": "Follower count."
          },
          "following_count": {
            "type": "integer",
            "nullable": true,
            "description": "Following count."
          },
          "created_at": {
            "type": "string",
            "nullable": true,
            "description": "Account creation timestamp in Twitter date format."
          },
          "profile_image_url": {
            "type": "string",
            "nullable": true,
            "description": "Avatar image URL."
          },
          "is_identity_verified": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account has completed X's identity verification. Null when the profile carries no verification_info block (an honest \"not available\", never a fabricated value)."
          },
          "verified_since": {
            "type": "string",
            "nullable": true,
            "description": "Timestamp the account was verified, as the raw epoch-milliseconds string X emits; null when not available."
          },
          "account_based_in": {
            "type": "string",
            "nullable": true,
            "description": "Country the account is based in, from X's \"About this account\" transparency panel; null when the panel is unavailable."
          },
          "created_via": {
            "type": "string",
            "nullable": true,
            "description": "How the account was created, from X's \"About this account\" transparency panel, for example \"United States App Store\". X names this field `source` upstream; it is surfaced here as created_via (the \"connected via / created via\" concept). Null when the panel is unavailable."
          },
          "username_changes": {
            "type": "object",
            "nullable": true,
            "description": "Username-change history from X's \"About this account\" transparency panel; null when the panel is unavailable.",
            "properties": {
              "count": {
                "type": "integer",
                "description": "Number of times the account has changed its username."
              },
              "last_changed_at": {
                "type": "string",
                "nullable": true,
                "description": "When the username was last changed, as the raw epoch-milliseconds string X emits; null when the account has never changed its username (count is 0)."
              }
            }
          },
          "created_country_accurate": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether X considers account_based_in an accurate reflection of the account's country of origin; null when the transparency panel is unavailable."
          },
          "location_accurate": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether X considers the self-reported location accurate; null when the transparency panel is unavailable."
          },
          "learn_more_url": {
            "type": "string",
            "nullable": true,
            "description": "X help-center link explaining the \"About this account\" transparency data; null when the panel is unavailable."
          },
          "protected": {
            "type": "boolean",
            "nullable": true,
            "description": "Whether the account is locked, so only approved followers can see its posts. Null on a trimmed user object that carries no protected key, which is an honest \"not available\" rather than a claim the account is public."
          },
          "affiliate_label": {
            "type": "object",
            "nullable": true,
            "description": "The affiliation badge X shows beside the display name, linking the account to a parent organization. Null when the account has no affiliation.",
            "properties": {
              "description": {
                "type": "string",
                "nullable": true,
                "description": "The parent organization's display name, for example \"X\"."
              },
              "badge_url": {
                "type": "string",
                "nullable": true,
                "description": "URL of the small badge image X renders next to the name."
              },
              "url": {
                "type": "string",
                "nullable": true,
                "description": "Link to the parent organization's profile."
              }
            }
          },
          "about_profile": {
            "type": "object",
            "description": "The profile About card and the \"About this account\" transparency panel grouped into one object, alongside the flat fields above. Every member mirrors a flat field of the same meaning except birthdate, which appears nowhere else in the response. The object itself is always present on a resolved profile; each member is null when X did not send it.",
            "properties": {
              "bio": {
                "type": "string",
                "nullable": true,
                "description": "Profile bio text. Same value as the flat description field."
              },
              "location": {
                "type": "string",
                "nullable": true,
                "description": "Self-reported location. Same value as the flat location field, and an empty string when the account set none."
              },
              "website": {
                "type": "string",
                "nullable": true,
                "description": "Linked website URL. Same value as the flat url field, and an empty string when the account set none."
              },
              "birthdate": {
                "type": "object",
                "nullable": true,
                "description": "Birthday from the About card, returned only when the account has one set and makes it visible. Null otherwise. Parts X withholds come back null individually, so a birthday shown as a day and month with no year returns year null.",
                "properties": {
                  "day": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Day of the month."
                  },
                  "month": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Month number, 1 for January."
                  },
                  "year": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Year; null when the account hides it."
                  },
                  "visibility": {
                    "type": "string",
                    "nullable": true,
                    "description": "Who the account shows the birthday to, for example Public, Followers, or Self."
                  }
                }
              },
              "account_based_in": {
                "type": "string",
                "nullable": true,
                "description": "Country the account is based in, from the transparency panel. Same value as the flat account_based_in field."
              },
              "created_via": {
                "type": "string",
                "nullable": true,
                "description": "How the account was created, for example \"United States App Store\" or \"Web\". Same value as the flat created_via field."
              },
              "username_changes": {
                "type": "object",
                "nullable": true,
                "description": "Username-change history from the transparency panel. Same value as the flat username_changes field.",
                "properties": {
                  "count": {
                    "type": "integer",
                    "description": "Number of times the account has changed its username."
                  },
                  "last_changed_at": {
                    "type": "string",
                    "nullable": true,
                    "description": "When the username was last changed, as the raw epoch-milliseconds string X emits; null when the account has never changed it."
                  }
                }
              },
              "created_country_accurate": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether X considers account_based_in an accurate reflection of where the account was created."
              },
              "location_accurate": {
                "type": "boolean",
                "nullable": true,
                "description": "Whether X considers the self-reported location accurate."
              },
              "learn_more_url": {
                "type": "string",
                "nullable": true,
                "description": "X help-center link explaining the transparency data."
              }
            }
          },
          "identity_label": {
            "type": "object",
            "nullable": true,
            "description": "The identity badge X shows on business and organisation profiles. Three states, and they are not interchangeable: null means X sent no block, so we do not know; an object whose label is null means X sent an empty block, so the account has no identity label; an object with a populated label is a real badge. Null on every account sampled so far.",
            "properties": {
              "label": {
                "type": "object",
                "nullable": true,
                "description": "The badge itself. Null when X sent the block but the account carries no label.",
                "properties": {
                  "description": {
                    "type": "string",
                    "nullable": true,
                    "description": "The label text, for example the organisation name."
                  },
                  "badge_url": {
                    "type": "string",
                    "nullable": true,
                    "description": "URL of the badge image X renders beside the display name."
                  },
                  "url": {
                    "type": "string",
                    "nullable": true,
                    "description": "Link the badge points to."
                  },
                  "url_type": {
                    "type": "string",
                    "nullable": true,
                    "description": "The kind of link X attached to the badge."
                  },
                  "display_type": {
                    "type": "string",
                    "nullable": true,
                    "description": "How X displays the label on the profile."
                  },
                  "label_type": {
                    "type": "string",
                    "nullable": true,
                    "description": "The label category X assigned, for example a business or government label."
                  }
                }
              }
            }
          }
        }
      },
      "PageInfo": {
        "type": "object",
        "description": "Cursor-pagination fields present on every paged response.",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Number of items returned in this page."
          },
          "next_cursor": {
            "type": "string",
            "nullable": true,
            "description": "Opaque cursor for the next page. Null on the final page for list and affiliate endpoints; follower-graph endpoints return a non-null cursor even on the last page, so stop when the collection array is empty."
          }
        }
      },
      "Relationship": {
        "type": "object",
        "description": "The directional follow/block/mute relationship between a source and target account.",
        "properties": {
          "source_id": {
            "type": "string",
            "description": "Numeric ID of the source account."
          },
          "target_id": {
            "type": "string",
            "description": "Numeric ID of the target account."
          },
          "following": {
            "type": "boolean",
            "description": "True when the source account follows the target."
          },
          "followed_by": {
            "type": "boolean",
            "description": "True when the target account follows the source."
          },
          "blocking": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the source blocks the target; null when not available."
          },
          "blocked_by": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the source is blocked by the target; null when not available."
          },
          "muting": {
            "type": "boolean",
            "nullable": true,
            "description": "True when the source mutes the target; null when not available."
          },
          "can_dm": {
            "type": "boolean",
            "description": "True when the source can send a direct message to the target."
          }
        }
      },
      "DMConversation": {
        "type": "object",
        "description": "A Direct Message conversation (inbox entry).",
        "properties": {
          "conversation_id": {
            "type": "string",
            "description": "Conversation ID; pass to the DM conversation endpoint to read messages."
          },
          "type": {
            "type": "string",
            "nullable": true,
            "description": "Conversation type, for example ONE_TO_ONE or GROUP_DM; may be null."
          },
          "participants": {
            "type": "array",
            "description": "Numeric user IDs of the participants.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "DMMessage": {
        "type": "object",
        "description": "A single Direct Message within a conversation.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Numeric message ID as a string."
          },
          "time": {
            "type": "string",
            "nullable": true,
            "description": "Send time in epoch milliseconds as a string; may be null."
          },
          "sender_id": {
            "type": "string",
            "nullable": true,
            "description": "Numeric ID of the sending account as a string; may be null."
          },
          "text": {
            "type": "string",
            "description": "Message body text."
          }
        }
      },
      "Community": {
        "type": "object",
        "description": "An X Community. Returned by Community Info and by Community Memberships, always with the same 24 keys, but NOT with the same fields populated: Community Info is served by a reduced X operation and returns admin, invites_policy, question, search_tags and members_facepile_ids empty, moderator_count as 0, and creator with id and name null. Community Memberships returns all of those filled. Each property below states which endpoint fills it, so a null can be read correctly rather than guessed at.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Numeric community id as a string."
          },
          "name": {
            "type": "string",
            "description": "The community's display name. Returned identically by both endpoints."
          },
          "description": {
            "type": "string",
            "nullable": true,
            "description": "The community's description text. Null when the community has not written one, which was 1 of 39 communities sampled. Returned identically by both endpoints."
          },
          "created_at": {
            "type": "integer",
            "description": "Millisecond epoch the community was created, as an integer rather than an ISO string. 0 when X did not send it. Returned identically by both endpoints."
          },
          "member_count": {
            "type": "integer",
            "description": "Total members. Returned identically by both endpoints: it matched exactly on all 10 communities read through both on 2026-08-17, including one at 265135 members. Contrast moderator_count, which does not match."
          },
          "moderator_count": {
            "type": "integer",
            "description": "Total moderators, but only from Community Memberships. COMMUNITY INFO RETURNS 0 HERE FOR EVERY COMMUNITY, including communities that demonstrably have moderators. On 10 communities read through both endpoints on 2026-08-17, Community Memberships returned 1 to 6 and Community Info returned 0 every time, and the Community Moderators roster independently agreed with Community Memberships on all 5 it was checked against. Read a 0 from Community Info as not reported, never as no moderators."
          },
          "join_policy": {
            "type": "string",
            "nullable": true,
            "description": "How the community admits members, passed through from X. Observed values: Open and RestrictedJoinRequestsRequireModeratorApproval. Only those two have been seen, which is not the same as those two being the whole set, so the field is passed through as a string rather than narrowed to an enum. Returned identically by both endpoints."
          },
          "invites_policy": {
            "type": "string",
            "nullable": true,
            "description": "Who may invite new members, passed through from X. Observed values: MemberInvitesAllowed and ModeratorInvitesAllowed. ONLY COMMUNITY MEMBERSHIPS RETURNS IT. Community Info returns null here for every community, so a null from that endpoint means the operation serving it does not carry the field, NOT that the community has no invite policy. The two cases cannot be told apart from the response alone, which is why it is stated here: on 2026-08-17 this field was non-null on all 10 communities read through Community Memberships and null on the same 10 read through Community Info minutes later. When you need the invite policy, read it from Community Memberships."
          },
          "is_nsfw": {
            "type": "boolean",
            "description": "Whether the community is flagged not-safe-for-work. Defaults to false when X does not send the field, so an absent flag reads as not flagged rather than as unknown. Returned identically by both endpoints."
          },
          "question": {
            "type": "string",
            "nullable": true,
            "description": "The join-screen prompt applicants answer, when the community sets one. Community Info returns null here for every community, including ones that do set a question, so read it from Community Memberships. A null from Community Memberships is the real answer and means the community asks nothing."
          },
          "primary_topic": {
            "type": "object",
            "nullable": true,
            "description": "The single topic X assigns the community. Null when the community has no topic. Community Info fills name but leaves topic_id null, so take topic_id from Community Memberships if you need the numeric id. X spells the name topic_name on the wire; it is normalised to name so a consumer reading Spaces topics and Community topics does not have to care.",
            "properties": {
              "topic_id": {
                "type": "string",
                "nullable": true,
                "description": "X's numeric topic id as a string, for example 603 for Entrepreneurship. Null on Community Info, which sends the name without the id."
              },
              "name": {
                "type": "string",
                "nullable": true,
                "description": "The topic's display name, for example Entrepreneurship or Education. Filled by both endpoints."
              }
            }
          },
          "search_tags": {
            "type": "array",
            "description": "The community's search tags, as plain strings. Community Info returns an empty array for every community, including ones that do have tags, so read this from Community Memberships. An empty array from Community Memberships is the real answer and means the community set none.",
            "items": {
              "type": "string",
              "description": "One search tag, without a leading hash."
            }
          },
          "rules": {
            "type": "array",
            "description": "The community's posted rules, in the order X returns them. Returned identically by both endpoints.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "Numeric rule id as a string."
                },
                "name": {
                  "type": "string",
                  "description": "The rule's title, which is the line X shows in the community's rule list."
                },
                "description": {
                  "type": "string",
                  "nullable": true,
                  "description": "The longer body text under the rule's title. Null when the community left it blank, which was 87 of 174 rules sampled on 2026-08-17, so expect roughly half of them to carry only a name. It is left null rather than filled with the rule name."
                }
              }
            }
          },
          "banner_url": {
            "type": "string",
            "nullable": true,
            "description": "The banner a client should actually render: the custom banner when the community set one, otherwise X's default. Computed for you, because both banners are always present and picking the wrong one silently shows every community the same stock gradient. Returned identically by both endpoints."
          },
          "custom_banner": {
            "type": "object",
            "nullable": true,
            "description": "The community's own banner, or null when the community never set one. Returned identically by both endpoints.",
            "properties": {
              "url": {
                "type": "string",
                "description": "Image URL on pbs.twimg.com."
              },
              "width": {
                "type": "integer",
                "description": "Image width in pixels."
              },
              "height": {
                "type": "integer",
                "description": "Image height in pixels."
              }
            }
          },
          "default_banner": {
            "type": "object",
            "nullable": true,
            "description": "X's stock banner. Present even when a custom banner exists, which is why banner_url is computed rather than left to the caller. Returned identically by both endpoints.",
            "properties": {
              "url": {
                "type": "string",
                "description": "Image URL on pbs.twimg.com."
              },
              "width": {
                "type": "integer",
                "description": "Image width in pixels."
              },
              "height": {
                "type": "integer",
                "description": "Image height in pixels."
              }
            }
          },
          "permalink": {
            "type": "string",
            "nullable": true,
            "description": "ALWAYS NULL, on both endpoints. X's community payload does not carry a permalink URL on either operation, and one is not synthesised here from the id. It was null on every community record sampled on 2026-08-17, through both endpoints. Build the link yourself: https://x.com/i/communities/ followed by the id."
          },
          "admin": {
            "allOf": [
              {
                "$ref": "#/components/schemas/User"
              }
            ],
            "description": "The community admin's full user profile, but only from Community Memberships. COMMUNITY INFO RETURNS NULL HERE FOR EVERY COMMUNITY: a full profile came back on all 10 communities read through Community Memberships on 2026-08-17 and null on the same 10 read through Community Info. If you need the admin and are starting from a community id, page Community Moderators, whose Admin row carries the same account."
          },
          "creator": {
            "allOf": [
              {
                "$ref": "#/components/schemas/User"
              }
            ],
            "description": "The community creator's full user profile, but only from Community Memberships. Community Info returns a REDUCED object here with id and name null, carrying the username and the verification flags and nothing else, so treat what Community Info gives you as a handle rather than a profile. Frequently the same account as admin, but do not assume it always is."
          },
          "members_facepile_ids": {
            "type": "array",
            "description": "User ids of the members X puts in the community facepile preview, ids only. Community Info returns an empty array for every community, so read this from Community Memberships. Use Community Members for the actual roster, which is the right tool whichever endpoint you started from.",
            "items": {
              "type": "string",
              "description": "A numeric user id as a string."
            }
          },
          "role": {
            "type": "string",
            "nullable": true,
            "description": "ALWAYS NULL, on both endpoints. It is the role of the ACCOUNT THAT MADE THE CALL, and these are pooled reads served by a rotating pool account, so any value here would describe a stranger. The key is kept rather than removed so it stays visible that X sends this field and we decline to answer it. For a real per-member role, use Community Members, whose members[].role is about that member and not about the caller."
          },
          "can_join": {
            "type": "boolean",
            "nullable": true,
            "description": "ALWAYS NULL, on both endpoints, for the same caller-relative reason as role. It answers whether the CALLING account may join, and the calling account is one of ours. Use join_policy for the community's own admission rule, which is a real answer."
          },
          "is_pinned": {
            "type": "boolean",
            "nullable": true,
            "description": "ALWAYS NULL, on both endpoints, for the same caller-relative reason as role. It answers whether the CALLING account pinned this community."
          },
          "viewer_relationship_type": {
            "type": "string",
            "nullable": true,
            "description": "ALWAYS NULL, on both endpoints, for the same caller-relative reason as role. It is the viewer relationship, and the viewer is the pool account."
          }
        }
      },
      "ErrorEnvelope": {
        "type": "object",
        "description": "The uniform JSON body returned on every non-2xx response.",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "Machine-readable error code, for example bad_request, unauthorized, or not_found.",
            "example": "bad_request"
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation of the failure."
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>."
      }
    }
  }
}
