The X API, sold by the call.
Reads, search, timelines, extractions, real-time monitors, signed webhooks, and write actions — paid per request in USDC. No signup, no keys: the wallet is the account. Agents plug in over HTTP or MCP.
Quickstart
Three steps: install the skills into your agent, connect a wallet, and ask. Pick your agent and your wallet — everything below updates to that combination. Building against the raw API instead? The HTTP flow is under Machine specs.
recommended — Base · Solana · Tempo
- 1Add the skills
npx skills add lnvestor/twitr-skills
Restart the Claude Code session after installing so the skills load. Running scheduled cycles on Claude Code web routines? Include the AgentCash connector — see the scheduling reference inside the x-presence skill.
- 2Connect the wallet
Add AgentCash as an MCP server (available in every session):
claude mcp add agentcash --scope user -- npx -y agentcash@latest
New to AgentCash? Visit agentcash.dev/onboard first — connecting GitHub/X/LinkedIn earns a claim code worth up to $25 in free USDC.
- 3Say this to your agent“What is my AgentCash balance?”— confirms the wallet is wired up“What's trending in tech right now?”“What is @vercel posting about this week?”“Watch @competitor and tell me when they announce something.”
The first paid call answers with a 402 quoting the exact price — that's the quote, not an error; your wallet signs it and the data comes back. Failed calls are never charged.
How payment works
You pay per request — no subscription, no prepaid balance. Two rails, both settling on-chain in USDC:
The client signs a payment authorization into the X-PAYMENT header; we verify, run the call, and settle.
Answered via the Authorization: Payment challenge; same pay-and-retry loop.
Volume tools bill per returned item and require resultsLimit, so you never pay for more than you asked for. Resource-creating calls (extractions, monitors, writes, draws) require an Idempotency-Key — a retry replays the original result instead of charging twice.
The wallet is the account: signing in (free) with the same wallet shows your run history and balance in the dashboard or over the API.
Tools
14 tools, each priced per call or per returned item. Full input schemas live in the OpenAPI spec.
Monitors
A monitor watches one X account or one keyword query in real time. Pay on Base (x402) or Tempo (MPP) — a monitor is a stateful resource that needs a recoverable owner wallet, so Solana is not offered for it.
expires_at unless extended — no open-ended billing, and early deletion does not refund. Max 168 hours per purchase, 720 hours of forward window.under the hood — raw HTTP
POST /api/tools/x_monitor
Idempotency-Key: <uuid>
{ "action": "create", "username": "vercel", "hours": 24 }
{ "action": "create", "query": "\"launch week\"", "hours": 24 }
{ "action": "extend", "monitorId": "mn_…", "hours": 48 }
GET /api/monitors # free, wallet-signed — list + status
DELETE /api/monitors/{id} # free, wallet-signedEvents → your agent
Monitors emit 21 event types — post events (new posts, replies, reposts, quotes, media, links, polls, mentions, hashtags, long posts) for any monitor, plus profile-change events for account monitors. A terminal monitor.expired / monitor.deleted event fires once when a monitor ends, so silence is never ambiguous. Two ways to receive them — both free:
GET /api/monitors/{id}/events?after=… — strictly newer events, oldest first. 500 events / 24h retained, 60 reads/min.
Register an HTTPS endpoint; we POST a signed event the moment it fires. Max 3 webhooks per wallet.
HMAC-SHA256(secret, timestamp.rawBody) and constant-time-compare to X-Twitr-Signature; reject timestamps older than 5 minutes; dedupe on delivery_id and id; respond 2xx within 10 seconds. Retries back off over ~36 minutes; 50 consecutive failures auto-pause the webhook and a successful /test re-activates it.under the hood — a signed delivery
# headers: X-Twitr-Signature, -Timestamp, -Delivery, -Event
{
"type": "tweet.new",
"id": "ev_…",
"delivery_id": "dl_…",
"monitor_id": "mn_…",
"occurred_at": "2026-07-26T10:00:00Z",
"received_at": "2026-07-26T10:00:01Z",
"source": { "username": "vercel" },
"data": { "text": "…", "url": "https://x.com/…" }
}
# register one (free, wallet-signed) — secret is returned ONCE:
POST /api/webhooks {"url":"https://your-agent/hooks","eventTypes":["tweet.new"]}
GET /api/webhooks/{id}/deliveries # delivery log
POST /api/webhooks/{id}/rotate # new secret
POST /api/webhooks/{id}/test # signed test + un-pauseConnecting an X account
Write tools (post, like, follow, DM, profile, community) act through an X account you connect once. Here is exactly what happens:
pending_confirmation is still running: wait, never resend. One handle belongs to exactly one wallet, and ownership is re-checked server-side on every write.under the hood — raw HTTP
# 1) mint a connect link (free, wallet-signed). NO credentials here, ever.
POST /api/x-accounts/start {"username":"yourhandle"}
# -> 200 {connect_url:"https://twitr.sh/connect/<token>", expires_in:900}
# show connect_url to the user — they sign in to X in their own browser
# 2) poll until the handle links (the user may enter an emailed code on that page)
GET /api/x-accounts
# -> {status:"linked"} — now x_write can act as this handle
# 3) write (paid). a 202 pending_confirmation means DO NOT resend.
POST /api/tools/x_write
Idempotency-Key: <uuid>
{"action":"post","account":"yourhandle","text":"shipping day"}Errors & retries
Every non-2xx body is an RFC 9457 Problem (application/problem+json) extended with two machine-actionable fields: retryable — whether the same request, unchanged, may succeed if retried later — and hint, one concrete next step.
retryable: true is always safe. 429s carry a Retry-After header; a 404 for a wrong tool name lists valid_tools so a bad guess self-heals in one read.{
"type": "https://paymentauth.org/problems/records-cap-required",
"title": "Records Cap Required",
"status": 400,
"detail": "This operation is billed per returned item and requires resultsLimit…",
"retryable": false,
"hint": "Add resultsLimit (integer 1-10000) to the request body."
}An unknown tool name is rare in practice: the MCP tool names (x_radar, x_draws, x_compose) are accepted as aliases of their route paths, so the natural guess resolves.
Machine specs
- /openapi.json — full OpenAPI 3.1 with per-tool schemas + payment discovery.
- /llms.txt — LLM-friendly index.
- /skill.md — installable agent skill: the full automation playbook.
POST /api/mcp— MCP endpoint; tools are payment-gated with a JSON-RPC 402. (tools/list is free — only tools/call is gated.)- /.well-known/x402 · /.well-known/mpp.json — payment-protocol discovery.
# 1) probe the price (unpaid) — returns 402 with the amount
curl -X POST https://twitr.sh/api/tools/x_read \
-H 'Content-Type: application/json' \
-d '{"resource":"get-tweet","id":"2079908425904042170"}'
# 2) pay the 402 in USDC and retry the same request → 200 + data
# (x402-aware clients do steps 1–2 automatically)