# Site API (/docs/api/site)

When an editor [signs in on your site](/docs/guides/site-editing), your server holds a **site token** (`cms_s_…`) for them. The SDK's `createSiteEditing` handler forwards the prompt bar's `/cms/api/…` calls here, so you only need this API when building that handler yourself.

`Authorization: Bearer cms_s_…`, from your server only. The token acts as the editor, with their [role](/docs/guides/roles) at the time of each request, in one space environment, and expires after 8 hours.

| Endpoint                                 | Does                                                                       |
| ---------------------------------------- | -------------------------------------------------------------------------- |
| `POST /api/site/v1/token`                | Trades the one-time code and PKCE verifier for a site token                |
| `GET /api/site/v1/session`               | Who, where, and `features` (`prompt`, `create`, `save`, `publish`, `form`) |
| `DELETE /api/site/v1/session`            | Signs out                                                                  |
| `POST /api/site/v1/entries`              | A new page from a prompt, stored as a draft (`201`)                        |
| `GET /api/site/v1/entries/{id}`          | The stored draft and its `draftRevision`                                   |
| `POST /api/site/v1/entries/{id}/preview` | Unsaved content, shaped like the delivery API                              |
| `POST /api/site/v1/entries/{id}/prompt`  | A prompt applied to unsaved content; saves nothing                         |
| `POST /api/site/v1/entries/{id}/view`    | Unsaved content as a prompt sees it, for editing as JSON                   |
| `POST /api/site/v1/entries/{id}/apply`   | Changes to that view applied to unsaved content; saves nothing             |
| `GET /api/site/v1/pages`                 | Every page, drafts included, with its paths per locale                     |
| `POST /api/site/v1/entries/{id}/save`    | Stores content as the draft (`baseRevision`; `409` on conflict)            |
| `POST /api/site/v1/entries/{id}/publish` | Publishes the stored draft                                                 |
| `POST /api/site/v1/form`                 | A URL of the entry form page (`/site/form#code=…`) for the bar to frame    |
| `GET /api/delivery/v1/…`                 | Drafts, as with a preview token                                            |

`features` tells the prompt bar what to offer: readers get none, and see drafts only. Errors are `{ "error": "…" }`; `prompt` and `entries` (a new page) take 20 a minute per person and answer `429` with `Retry-After` past that.

## The form's routes [#the-forms-routes]

The prompt bar's **Form** is Content's own page `/site/form`, framed by your site. It trades the one-time code in its URL for a **form token** (`cms_f_…`), which it keeps in memory and calls these with. A form token only works here (never on the routes above or the delivery API), and expires or is revoked with the site token it was opened from. The site token itself works here too. All of them need edit rights.

| Endpoint                               | Does                                                                           |
| -------------------------------------- | ------------------------------------------------------------------------------ |
| `POST /api/site/v1/form/token`         | Trades the code (`{ code }`, no bearer) for `{ token, expiresAt, siteOrigin }` |
| `GET /api/site/v1/form/entries/{id}`   | What the form needs for the entry: model, locales, assets and entries it uses  |
| `GET /api/site/v1/form/entries`        | The entry picker: `q`, `type`, `limit`, `skip`                                 |
| `GET /api/site/v1/form/assets`         | The asset picker: `q`, `mimeType`, `tag`, `limit`, `skip`                      |
| `POST /api/site/v1/form/assets/upload` | Uploads (`multipart/form-data`, `file` fields)                                 |
| `GET /api/site/v1/form/assets/details` | One file for its details: `assetId`                                            |
| `POST /api/site/v1/form/assets/update` | Changes a file's `title`, `alt`, `focalPoint` or `tags` (`{ assetId, … }`)     |

Full request and response shapes are in [`/openapi.json`](https://content.obelism.studio/openapi.json) (tag Site).
