Skip to main content
Every Xitter instance has a public JSON API at https://<instance>/api/v1. Scripts and bots use it to read and post as their own account. Each instance also documents its API at /api.
Running a bot? It must follow the bot guidelines.
What a token sees is what its account sees: blocks, protected accounts and suspensions apply. Posts made through the API show “Xitter API” as their app.

Personal tokens

Make a token at /account/api. A read token can only look; a write token can also post, like and follow. Send it with every request:
Anyone holding a token can act as you. Changing or resetting your password revokes all API tokens, so make new ones for your scripts and bots afterward.

Apps for other people (OAuth 2)

For an app used by other people, register a public client at /account/apps/developer. Users review and revoke grants at /account/apps. The flow is OAuth 2 authorization code with mandatory PKCE (S256). Clients have no shared secret.
1

Make a verifier and challenge

Generate a random 43–128 character code_verifier and its SHA-256 base64url code_challenge. Generate a random state.
2

Send the user to authorize

Open https://<instance>/oauth/authorize with response_type=code, your client_id, the exact registered redirect_uri, scope=read or write, state, code_challenge and code_challenge_method=S256.
3

Exchange the code

After consent, check state, then form-POST the returned code with grant_type=authorization_code, client_id, redirect_uri and code_verifier to https://<instance>/oauth/token.
4

Call the API

Use access_token as the Bearer token.
Codes work once, for five minutes. Access tokens expire after 30 days; reauthorize to get a new one. HTTPS redirects and HTTP loopback redirects are accepted, and the redirect must match the registered URL exactly.

One app for every Xitter

Instead of registering on each instance, an app can use the HTTPS URL of a JSON document it hosts as its client_id (an OAuth client ID metadata document):
  • client_id must be the document’s own URL, exactly.
  • redirect_uris must be HTTPS on the document’s host.
  • logo_uri is optional: an HTTPS image on that host, shown as the app’s icon.
Instances that support this say so with client_id_metadata_document_supported in /.well-known/oauth-authorization-server.

Requests and responses

Bodies are JSON (or a form). Answers are JSON with the result in data, or {"error": "..."} with a 4xx or 5xx status.
The API sends CORS headers for any origin, since tokens are sent explicitly and never as cookies.

Paging

Lists take limit (20 by default, 100 at most). Lists that page return next_cursor: pass it back as cursor for the next page. It is null at the end.

Limits

The same as in the app, per 15 minutes: Every answer carries x-rate-limit-limit, x-rate-limit-remaining and x-rate-limit-reset (a Unix time). Over a limit you get 429 with retry-after.

Errors