diff --git a/docs.json b/docs.json index 31c71b113..16d4d359f 100644 --- a/docs.json +++ b/docs.json @@ -1041,6 +1041,7 @@ "pages": [ "xchat/media", "xchat/groups", + "xchat/bots", "xchat/real-time-events", "xchat/troubleshooting" ] @@ -1090,6 +1091,18 @@ "x-api/chat/finalize-chat-media-upload", "x-api/chat/download-chat-media" ] + }, + { + "group": "Bots", + "expanded": true, + "pages": [ + "x-api/bots/create-a-bot", + "x-api/bots/get-bots", + "x-api/bots/update-bot", + "x-api/bots/delete-bot", + "x-api/bots/rotate-bot-token", + "x-api/bots/revoke-bot-token" + ] } ] } diff --git a/xchat/bots.mdx b/xchat/bots.mdx new file mode 100644 index 000000000..43e4c43b3 --- /dev/null +++ b/xchat/bots.mdx @@ -0,0 +1,78 @@ +--- +title: "Manage bot accounts with the Chat API" +sidebarTitle: Bots +description: "Create and manage programmatic bot accounts for your project: mint bearer tokens, rotate or revoke them, and manage the bot's identity." +keywords: ["X bots", "bot accounts", "bot token", "create a bot", "rotate bot token", "app-only auth"] +--- + +A **bot** is a programmatic X account created by and belonging to your **project**. It is a real account with a user id, an @handle, and a display name, but it has no password and no login. The only way to act as a bot is its **bearer token**. + +Bot accounts carry an **"Automated by @owner"** label pointing to the X account that owns the client app. + +Endpoint details are under **API reference → Bots**. + +--- + +## Authentication + +All six bot endpoints use **OAuth 2.0 app-only** auth: authenticate with your app's bearer token. No user context and no OAuth scopes are required to call them. + +Every operation is scoped to the calling app's project. You can only list and manage bots that belong to that project. + +--- + +## Bot tokens + +- [`POST /2/bots`](/x-api/bots/create-a-bot) and [`POST /2/bots/:id/token`](/x-api/bots/rotate-bot-token) mint the bot's bearer token (format `xcbot_…`). The token is returned **once** and can never be retrieved again. Store it on receipt. +- A bot has **one active token**: any mint revokes the previously outstanding token(s). +- Token scopes default to `dm.read, dm.write, tweet.read, users.read, media.write`. A request may narrow to a subset of that set; requesting anything outside it returns a 400. The response includes `expires_at` (epoch milliseconds) and `scopes`. +- [`DELETE /2/bots/:id/token`](/x-api/bots/revoke-bot-token) revokes without minting a replacement, as a standard OAuth2-style kill switch. It responds with `{"data":{"revoked":true}}`. The account survives; rotate later to re-activate. + +--- + +## Lifecycle + +| Endpoint | What it does | +|:---------|:-------------| +| [`POST /2/bots`](/x-api/bots/create-a-bot) | Create a bot. Body: `handle` (required, 1–15 chars, letters/digits/underscore), `display_name` (optional, ≤50 chars, defaults to handle), `scopes` (optional subset). Returns 201 with `{id, username, name, token, expires_at, scopes}` | +| [`GET /2/bots`](/x-api/bots/get-bots) | List the project's bots: `{"data":[{id, name, username}], "meta":{result_count, max_bots}}` | +| [`POST /2/bots/:id/token`](/x-api/bots/rotate-bot-token) | Rotate: mints a new token, revokes the old. Body: optional `scopes` | +| [`PUT /2/bots/:id`](/x-api/bots/update-bot) | Update identity: `handle`, `display_name`, `dm_permission` (`everyone` \| `premium` \| `no_one`); at least one field. Returns `{"data":{"updated":true}}` | +| [`DELETE /2/bots/:id/token`](/x-api/bots/revoke-bot-token) | Revoke tokens, keep the bot | +| [`DELETE /2/bots/:id`](/x-api/bots/delete-bot) | Delete: revokes tokens, permanently destroys the bot's X account, removes it from the project. Returns `{"data":{"deleted":true}}` | + + +**Create is idempotent on handle.** Repeating a `POST /2/bots` whose handle already names one of the project's bots returns that same bot with a **freshly minted token**; the previous one is revoked. This makes retries safe when a response was lost, since the replaced token was never seen. A converge re-applies `display_name` if provided but never changes DM permission. + + +--- + +## Limits + +- Each project has a bot allowance set by its plan. `meta.max_bots` in the list response reports it; the default is 1. Creating past the cap returns an error. +- Rate limits are per-app, in 15-minute windows. + +--- + +## Example + +```bash +POST /2/bots +Authorization: Bearer + +{"handle": "my_support_bot", "display_name": "Support Bot"} +``` + +```json +201 +{ + "data": { + "id": "2075014963136012288", + "username": "my_support_bot", + "name": "Support Bot", + "token": "xcbot_…", + "expires_at": 1787761273000, + "scopes": ["dm.read", "dm.write", "tweet.read", "users.read", "media.write"] + } +} +```