# Twitter API Docs: Endpoints and Credits

Reference for the TwitterViewer API: authentication, convert, search, replies, trends, credits, errors, rate limits, MCP tools and the CLI.

Page: https://twitterviewer.app/docs/api

Authentication, endpoints, errors, rate limits, credits, MCP tools and the command-line tool. English only; code examples are the same in every language.

TwitterViewer is an independent service. It is not X's official API and is not affiliated with X Corp. It reads public posts only: it cannot post, like, follow, send messages or read private accounts.

## Overview

Base URL https://twitterviewer.app. Endpoints live under /api/v1. All endpoints are read-only and billed in credits (1 credit = 1 post returned).

| Endpoint | Method | What it does |
| --- | --- | --- |
| /api/v1/convert | POST, GET | A post, a thread or a profile as Markdown, Obsidian, text, JSON or PDF |
| /{handle}/status/{id} | GET | The same as convert, using the post address with the domain swapped |
| /api/v1/search | GET | Search public posts (Pro and Business) |
| /api/v1/replies | GET | The replies under a post |
| /api/v1/trends | GET | What is trending in a region |
| /api/v1/credits | GET | Your credit balance, free of charge |
| /mcp | POST | Remote MCP server (Streamable HTTP) |

## Authentication

Create a key at https://twitterviewer.app/account/api and send it as a Bearer token. The full key is shown once. Keys per account: Plus 2, Pro 5, Business 20, and 1 for a free account.

```
Authorization: Bearer tv_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## Convert a link

POST or GET /api/v1/convert

| Name | Type | Description |
| --- | --- | --- |
| url | string, required | A link to a post, thread or profile on x.com or twitter.com, or the same address on twitterviewer.app. |
| scope | thread / post / conversation | Default `thread`: the author's connected posts. `post`: only that post. `conversation`: the thread plus the first page of replies. Profile links always return recent posts. |
| format | json / markdown / obsidian / text / pdf | Default `json`. `obsidian` adds YAML frontmatter. `pdf` returns a PDF file and is part of Pro and Business. |
| stats | all / root / off | Default `all`: counts on every post. `root`: only the first post. `off`: no counts. |
| max | integer 1–200 | Profile links only: how many recent posts to return. Default 20. |
| replies | boolean | Profile links only: include the account's replies. Default false. |
| reposts | boolean | Profile links only: include reposts. Default false. |
| paper | a4 / letter | Page size for `format=pdf`. Default `a4`. |

```bash
curl https://twitterviewer.app/api/v1/convert \
  -H "Authorization: Bearer $TWITTERVIEWER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://x.com/username/status/1234567890123456789",
    "scope": "thread",
    "format": "markdown"
  }'

# or just swap the domain
curl -H "Authorization: Bearer $TWITTERVIEWER_API_KEY" \
  https://twitterviewer.app/username/status/1234567890123456789
```

| Field | Type | Description |
| --- | --- | --- |
| kind | string | post, thread, conversation or profile. |
| title | string | The first 60 characters of the first post, cut at a word boundary. For profiles, "Posts by Name (@handle)". |
| sourceUrl | string | The x.com address of the source. |
| author | object | Name, handle, bio, followers, verification and join date, as far as X shows them. |
| markdown | string | The rendered document in the requested format (markdown or obsidian). |
| text | string | The same content as plain text. |
| posts | array | The posts as structured data: id, text, date, media, counts, quoted post. |
| replies | array | Replies, only for scope=conversation. |
| postsReturned | integer | How many posts this call returned. This is the credit cost. |
| wordCount | integer | Words in the rendered document. |
| credits | object | `charged` and `remaining` credits after this call. |

```json
{
  "kind": "thread",
  "title": "How we shipped the new release:",
  "sourceUrl": "https://x.com/username/status/1234567890123456789",
  "author": { "handle": "username", "name": "Example", "followers": 1204 },
  "postsReturned": 31,
  "wordCount": 2214,
  "markdown": "# How we shipped the new release…\n\nThread by @username…",
  "text": "How we shipped the new release…",
  "posts": [ { "id": "1234567890123456789", "text": "…" }, … ],
  "replies": [],
  "credits": { "charged": 31, "remaining": 2969 }
}
```

With format markdown, obsidian or text and the header `Accept: text/markdown` the body is only the document (post count in the x-posts-returned header). format=pdf returns application/pdf (Pro and Business).

## Swap the domain

Domain swap: GET /{handle}/status/{id} or /{handle} on twitterviewer.app (replace x.com in the link) with "Authorization: Bearer <API key>" and an Accept header that does not include text/html returns Markdown; ?scope=post|thread|conversation, ?format=obsidian|text|json and ?max= work as in convert. Without a key the call returns 401 and nothing is fetched from X; browsers get the normal page.

## Search posts

GET /api/v1/search (Pro and Business, needs a connected X account)

| Name | Type | Description |
| --- | --- | --- |
| q | string, required | The query, with X search operators. Up to 500 characters. |
| max | integer 1–100 | How many posts to return. Default 20. |

## Read replies

GET /api/v1/replies

| Name | Type | Description |
| --- | --- | --- |
| url | string, required | A link to an X post. |
| max | integer 1–100 | How many replies to return. Default 20. |

## Trends

GET /api/v1/trends (1 credit per call)

| Name | Type | Description |
| --- | --- | --- |
| region | string | One of worldwide, united-states (default), united-kingdom, japan, saudi-arabia, india, brazil or germany. |

## Check your credits

GET /api/v1/credits (free): returns total, plan { remaining, granted, expiresAt } and purchased { remaining }.

## How credits are counted

- 1 credit = 1 post returned. A quoted post counts as one more post. Author details are free.
- Replies, search results and conversation replies count the same way. Trends cost 1 credit per call.
- Failed calls are free: errors, empty results and PDF rendering failures are not charged.
- A call is refused with `402` when the balance is 0. If the balance is lower than the result, you get as many posts as the balance covers.
- Credits are spent from the pool that expires first: the monthly plan pool, then purchased credits.
- Every account gets 50 credits once, at sign-up. Plans add a monthly pool; credit packs (1,000 credits, 6,000 credits, 20,000 credits) are one-time and never expire.
- The same key asking for the same link with the same parameters within 10 minutes is not charged twice. On the website everyone gets 1 free conversion a day; the API always uses credits.

## Rate limits and plans

| Plan | Credits a month | Requests a minute, API keys, PDF |
| --- | --- | --- |
| Free | 0 (+ 50 at sign-up) | 10 a minute · 1 key · no PDF |
| Plus | 3,000 | 30 a minute · 2 keys · no PDF |
| Pro | 8,000 | 60 a minute · 5 keys · PDF |
| Business | 25,000 | 300 a minute · 20 keys · PDF |

## Errors

Error body: { "error": { "code", "message", "retryAfterSec?", "details?" } }

| Code | Status | When |
| --- | --- | --- |
| INVALID_INPUT | 400 | A parameter is missing or has the wrong value, or the link is not an X post or profile. |
| UNAUTHORIZED | 401 | No API key, or the key is wrong or deleted. Nothing is fetched from X and nothing is charged. |
| LIMIT_REACHED | 402 | `details.reason` says why: `INSUFFICIENT_CREDITS` (balance too low; `details.required` and `details.balance`) or `SERVER_PDF_REQUIRES_PRO` (PDF output needs Pro or Business). |
| PROTECTED | 403 | The account is protected. Only public content is available. |
| X_ACCOUNT_REQUIRED | 403 | Search needs a Pro or Business plan with a connected X account. `details.reason` is `upgrade` or `connect`. |
| NOT_FOUND | 404 | The post or account does not exist or was deleted. |
| SUSPENDED | 410 | The account is suspended. |
| RATE_LIMITED | 429 | More than your plan allows per minute. Wait `retryAfterSec` seconds (also in the Retry-After header). |
| UPSTREAM | 502 | The X data source failed. Nothing is charged; retry in a few seconds. |
| SERVICE_UNAVAILABLE | 503 | A part of the service, such as PDF rendering, is not available right now. Nothing is charged. |

## MCP server

MCP server: https://twitterviewer.app/mcp (Streamable HTTP; OAuth sign-in in the browser, or send "Authorization: Bearer <API key>"; OAuth metadata at https://twitterviewer.app/.well-known/oauth-protected-resource). Claude Code: claude mcp add --transport http twitterviewer https://twitterviewer.app/mcp; Cursor: {"mcpServers":{"twitterviewer":{"url":"https://twitterviewer.app/mcp"}}}; Codex: [mcp_servers.twitterviewer] url = "https://twitterviewer.app/mcp". Read-only tools: convert_x_url, search_x_posts, get_x_replies, get_x_trends, get_credits. Setup for Claude Code, Claude, Cursor and Codex: https://twitterviewer.app/twitter-mcp-server

| Tool | Arguments | What it does |
| --- | --- | --- |
| convert_x_url | url, scope, format, stats, max | Turns a post, thread or profile link into Markdown, Obsidian, text or JSON. |
| search_x_posts | query, max | Searches public posts (Pro and Business). |
| get_x_replies | url, max | Reads the replies under a post. |
| get_x_trends | region | Lists trends for a region. |
| get_credits | none | Shows the balance. |

## Command-line tool

Command-line tool: `npx twitterviewer <link>` (options --scope, --format md|obsidian|json|text|pdf, --stats, -o file), `twitterviewer login`, `twitterviewer credits`; reads the TWITTERVIEWER_API_KEY environment variable.

| Argument | Type | Description |
| --- | --- | --- |
| <link> or @handle | string | A post, thread or profile link, or an @handle for a profile's recent posts. |
| --scope | thread / post / conversation | Same as the API. Default `thread`. |
| --format | md / obsidian / json / text / pdf | Output format. Default `md`. `pdf` needs `-o` and a Pro or Business plan. |
| --stats | all / root / off | Engagement numbers. Default `all`. |
| --max | integer 1–200 | Profile only: how many posts to export. Default 20. |
| --replies, --reposts | flags | Profile only: include replies or reposts. |
| --paper | a4 / letter | PDF paper size. Default `a4`. |
| -o, --output | path | Write to a file instead of the terminal. |

Exit codes: 0 ok, 1 error, 2 bad arguments, 3 sign-in or credits needed.

## Agent Skill

Agent Skill: https://twitterviewer.app/.well-known/agent-skills/twitterviewer/SKILL.md (index: https://twitterviewer.app/.well-known/agent-skills/index.json) tells an agent what to do when it meets an X link.
