# X (Twitter) JSON API

Access Twitter/X data as JSON via [x402](https://x402.org) micropayments on Base.
Each call costs a small amount of USDC (default **$0.005**); read-only, no X login
required.

Base URL: **`https://x.1x402.sh`**

## When to use

- Look up an X user's profile, bio, follower counts, or pinned tweet
- Fetch a user's timeline (tweets, replies, or media)
- Read a single tweet — with its conversation (replies), or on its own
- Read a tweet's edit history (latest plus prior versions)
- Search tweets or users; resolve a hashtag
- Read X Lists (info, timeline, members) or a broadcast
- Resolve a numeric user id → username

## Payment

Endpoints under `/api/*` are gated by **x402 on Base** (asset: native USDC).
A request with no payment returns `402` with a `PAYMENT-REQUIRED` header describing
the price and recipient; an x402-capable client pays and retries automatically.

- **Pay with an x402 client**, e.g. [agentcash](https://agentcash.dev):
  ```bash
  npx agentcash fetch https://x.1x402.sh/api/jack/profile
  ```
  The client needs native **USDC on Base** in its wallet. Bridged/wrapped USDC
  (e.g. Stargate) is not accepted — x402 requires EIP-3009 native USDC.
- **Bypass cache** on any endpoint with `?no-cache` to force fresh data.

## Endpoints

| Method & path | Returns |
|---------------|---------|
| `GET /api/:name` | user timeline (append `/with_replies` or `/media`) |
| `GET /api/:name/profile` | user object + photo rail + pinned tweet |
| `GET /api/:name/about` | account info (join date, location, verification) |
| `GET /api/:name/pinned` | the user's pinned tweet |
| `GET /api/:name/status/:id` | a tweet + conversation (before/after/replies) |
| `GET /api/i/status/:id` | a single tweet, without its conversation |
| `GET /api/:name/status/:id/history` | a tweet's edit history (`latest` + prior versions) |
| `GET /api/search?q=…` | tweet search (or user search for `@`/`f:user` queries) |
| `GET /api/hashtag/:tag` | redirect to search for `#tag` |
| `GET /api/:name/lists/:slug` | a List by owner + slug |
| `GET /api/i/lists/:id` | a List by id |
| `GET /api/i/lists/:id/timeline` | tweets in a List |
| `GET /api/i/lists/:id/members` | members of a List |
| `GET /api/i/user/:id` | `{ "username": … }` for a numeric user id |
| `GET /api/i/broadcasts/:id` | a broadcast |

`:name` is an X handle without `@`. Pagination: pass the response's
`pagination.bottom` (or `replies.bottom`) cursor back as `?cursor=…`.

## Response format

Most endpoints wrap data as `{ "code": 0, "data": … }` on success and
`{ "code": -1, "error": …, "error_type": … }` on error (the List endpoints
return the bare object). Examples:

```bash
# profile
curl -s https://x.1x402.sh/api/jack/profile | jq '.data.user | {username, followers, verifiedType}'

# timeline (first page) + next cursor
curl -s https://x.1x402.sh/api/jack | jq '{next: .data.pagination.bottom, tweets: [.data.timeline[] | {id, text}]}'

# a tweet + its conversation
curl -s https://x.1x402.sh/api/jack/status/20 | jq '.data.tweet | {text, time, stats}'

# just the tweet (no conversation)
curl -s https://x.1x402.sh/api/i/status/20 | jq '.data | {text, time, stats}'

# a tweet's edit history
curl -s https://x.1x402.sh/api/jack/status/20/history | jq '{latest: .data.latest.text, versions: (.data.history | length)}'

# search
curl -s "https://x.1x402.sh/api/search?q=typescript" | jq '.data.timeline | length'
```

A `Tweet` includes `id`, `text`, `time` (unix), `user`, `stats`
(replies/retweets/likes/quotes/views), and `media` (photos/videos/gifs);
retweets/quotes/polls/cards are nested when present. A `User` includes
`username`, `fullname`, `bio`, `followers`, `following`, `verifiedType`,
`joinDate`, etc.

## Notes

- Read-only mirror of X's public data; no posting/auth.
- Stable entities (profiles, lists, broadcasts) are cached; timelines, search,
  and conversations are always fresh.
- Errors surface as the normal envelope, e.g. `404 not_found` for a missing
  user/tweet, `429 rate_limited`, `402` when payment is required.
