# Agent API and MCP (/docs/api/agents)

The agent API does what the dashboard does, with a bearer token, for agents and for anyone scripting Content. The same operations are [MCP tools](#mcp). The step-by-step guide is [`/agent.md`](https://content.obelism.studio/agent.md), written for agents; the full reference is [`/openapi.json`](https://content.obelism.studio/openapi.json).

Send and expect JSON. Errors are [problem JSON](/docs/api/errors) with a stable `code` and a `hint`. Content's endpoints are on `content.obelism.studio`: www serves accounts, organizations and spaces, and answers a Content path with a `404` that says so.

## Signing in [#signing-in]

Accounts are shared by every Obelism product and served by www.obelism.studio. Content answers `/api/agent/auth/*` with a `308` there, so following redirects works too.

```http
POST https://www.obelism.studio/api/agent/auth/sign-in
{ "email": "…", "password": "…" }
```

answers `{ "token", "tokenType": "Bearer", "expiresAt" }`. Send it as `Authorization: Bearer <token>`. It is the same session a browser login holds, lasting 30 days, renewed while in use. `GET /api/agent/me` shows whose it is.

For working on a space session after session, don't sign in again every time: create a **management token of your own** — `POST …/{environment}/api-tokens` with `{ "name": "…", "kind": "management", "scopes": ["model", "content"] }` —, put its `token` (a `cms_m_…` value, shown once) in an untracked environment file, and send that instead of the session token. A `content` scope reads and writes the environment's content through this API without your session (migrations, imports); `model` — the default without `scopes` — keeps the model in Git through the [management API](/docs/api/management). Creating or revoking tokens needs the developer or admin role and is refused in production (`production_protected`): a person makes production's tokens in the dashboard. Revoking a lost one is `POST …/api-tokens/{tokenId}/revoke`.

## Where to work [#where-to-work]

```http
GET /api/agent/organizations                     → organizations, your role in each
GET /api/agent/organizations/{org}/spaces        → spaces, their locales
POST /api/agent/organizations/{org}/spaces       → a new space (admins and developers), optionally from a `starter` model
PATCH /api/agent/organizations/{org}/spaces/{space} → rename it, or change its locales
```

For the whole space, under `/api/agent/organizations/{org}/spaces/{space}`:

| Request                       | Does                                                                                            |
| ----------------------------- | ----------------------------------------------------------------------------------------------- |
| `GET members`                 | Who may open the space, with their role in it                                                   |
| `PUT members/{userId}`        | A member's [role in this space](/docs/guides/roles#roles-per-space) (admins)                    |
| `GET locale-removal?locale=…` | What [removing a locale](/docs/guides/locales#removing-a-locale) would delete, before you do it |
| `GET usage`                   | [Delivery API requests](/docs/api/delivery#rate-limits-and-usage) per environment and day       |

Everything else is under `/api/agent/organizations/{org}/spaces/{space}/{environment}`:

| Area           | Operations                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Content model  | list, read, save, replace and delete content types (`content-types`, `content-types/{apiId}`; a new type gets its kind's [template fields](/docs/guides/content-model#new-types-start-with-the-usual-fields), listed by `GET /api/agent/content-type-templates`; saving an existing type **merges** the fields it sends, keeping the ones it leaves out, and `removeFields` names the ones to drop, deleting their values); the whole model as a file (`GET model`, `POST model/plan` — answers a `planId` — `POST model/apply` by that or by the file)                                                                        |
| Entries        | list (`search`, `contentType`, `status`, `parentId`, `sort`, `limit`, `skip`), validate (`POST entries/validate`, a dry run of `create`), create, read, save (`baseRevision`), publish (optionally some `locales`, and `exclude` for a [shared block's](/docs/guides/content-model#shared-blocks) live pages), unpublish, schedule, move (with `slugs` per locale), duplicate, detach a shared block (`POST entries/{id}/detach-block` with `uid`, `baseRevision`), delete, preview; publish impact (`GET entries/{id}/publish-impact`); [bulk actions](/docs/guides/publishing#several-entries-at-once) (`POST entries/bulk`) |
| Review         | `GET`/`POST entries/{id}/review`, and `…/review/approve` (optionally `exclude` for a shared block), `…/review/send-back`, `…/review/withdraw` ([review before publishing](/docs/guides/publishing#review-before-publishing))                                                                                                                                                                                                                                                                                                                                                                                                   |
| Comments       | `GET`/`POST entries/{id}/comments`, `PATCH`/`DELETE comments/{commentId}` ([comments](/docs/guides/comments))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| Translation    | `POST entries/{id}/translate` (one entry), `POST translations` (many, in the background), `GET translations` (what is waiting) ([translating](/docs/guides/locales#agents))                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| History        | `GET entries/{id}/versions`, `GET …/versions/{versionId}`, `POST …/versions/{versionId}/restore`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| Trash          | `GET trash`, `POST trash/{id}/restore`, `DELETE trash/{id}`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| Redirects      | `GET redirects`, `POST redirects/create` (`from`, `to`: a path, with or without a leading `/`, or an absolute URL), `POST redirects/delete` ([redirects](/docs/guides/redirects#adding-one-by-hand))                                                                                                                                                                                                                                                                                                                                                                                                                           |
| Plugins        | `GET plugins`: the [plugins](/docs/guides/plugins) on in the environment. A field whose `editor` names one has it as its input for people; write its value as for any field of its type                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| Assets         | upload (multipart with a `file` field up to 50 MB, a `filename` field names it, or base64 in a JSON body up to 1 MB; the bytes prove the type and an image's `width`/`height`, and a false renderable-image claim is refused; `POST uploads/assets` + `PUT` its `uploadUrl` + `POST assets/from-upload` takes more, videos up to 100 MB), list (`search`, `mimeType`, `tag`, `limit`, `skip`), read, change (alt, title, focal point, `tags`, `private`, `revokeLinks`), replace the file (`PUT assets/{id}/file`, with the same body), delete                                                                                 |
| Designs        | `POST uploads` (a URL to `PUT` a file to) and `POST design-imports`: a [page from Claude Design](/docs/guides/claude-design) as a draft on the space's blocks                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| Promotion      | `POST promotion/plan`, `POST promotion/apply`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| Export, import | `GET export`, `POST uploads/import` (a URL to `PUT` an export file to, so megabytes skip the agent's context), `POST import/plan`, `POST import/apply` (by `file` or that `uploadId`) ([export and import](/docs/guides/environments#export-and-import)); `GET export/sql` for portable SQL files ([taking your content elsewhere](/docs/guides/environments#taking-your-content-elsewhere))                                                                                                                                                                                                                                   |
| Activity       | `GET audit-log` ([activity](/docs/guides/activity))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| Improve        | `GET improve`: the tests and flags the [improve block](/docs/guides/ab-tests) can name                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Connect a site | `GET setup`, [API tokens](/docs/guides/api-tokens), webhooks (create, edit, pause, rotate the secret, test, delete) and their deliveries (list, redeliver), `GET`/`PATCH settings` (preview URL, product and collection paths, prompt endpoint, publishing, the model's source, AI translation)                                                                                                                                                                                                                                                                                                                                |

Your [role](/docs/guides/roles) decides what you may do. In production the agent API doesn't create or revoke tokens, add or delete webhooks, or change settings (`403 production_protected`): a person does those in the dashboard.

## Saving content [#saving-content]

To change an entry, read it, change its `draft`, and send the whole content back with the revision you read:

```http
GET …/entries/{id}                          → entry.draft, entry.draftRevision
PUT …/entries/{id}  { "content": { … }, "baseRevision": 3 }
```

A `409 conflict` means someone saved in between: read again and redo the change. Saving checks value shapes; publishing also enforces required fields. Rich text may be sent as [Markdown](/docs/api/rich-text#writing-it-as-markdown).

## MCP [#mcp]

The MCP server is `https://content.obelism.studio/mcp` (Streamable HTTP). It signs in with OAuth 2.1 (a browser window asks you to approve the connection), so there is no token to copy; clients find everything through `/.well-known/oauth-protected-resource/mcp` and register with Dynamic Client Registration.

Each agent API operation is a tool named after its `operationId` in `/openapi.json` (`listContentTypes`, `createEntry`, `saveEntry`, `publishEntry`, `getProjectSetup`, …), taking the path parameters and body fields as one input. Tools run as you, within your role; a read-only grant (`cms:read`) gets only the reading tools. See [connect an agent](/docs/getting-started/agents) to set one up.
