> ## Documentation Index
> Fetch the complete documentation index at: https://docs.soma.evarist.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API overview

> Base URL, authentication, errors, pagination and limits.

```text theme={null}
https://staging.soma.evarist.com/v1
```

The OpenAPI document is at [`/v1/openapi.json`](https://staging.soma.evarist.com/v1/openapi.json); every endpoint is in the **API reference** tab.

## Authentication

Send `Authorization: Bearer <token>`. Two kinds of token:

| Token | Get it | Can |
| - | - | - |
| **API key** `scribe_mcp_…` | Soma → Account settings → API keys | Read the workspaces chosen when it was created |
| **OAuth access token** `soma_at_…` | An OAuth 2.1 sign-in, as the CLI and MCP clients do | Act as the user: read, and write with the `knowledge:write` scope |

<Accordion title="Getting an OAuth token for your app">
  Soma's authorization server follows the MCP authorization spec. Discover it from `GET /.well-known/oauth-protected-resource/v1`, which points at `/.well-known/oauth-authorization-server`. Register your app with a Client ID Metadata Document (your `client_id` is the https URL of your metadata) or through Dynamic Client Registration (`POST /oauth/register`), then run the authorization-code flow with PKCE (S256) and `resource=https://staging.soma.evarist.com/v1`. Ask for `knowledge:read knowledge:write` to create workspaces and add documents. Access tokens last one hour; refresh tokens rotate.
</Accordion>

A request without a valid token gets `401` with a `WWW-Authenticate` header pointing at the metadata above. A read-only token used for a write gets `403` with type `insufficient_scope`.

## Errors

Every error has the same shape:

```json theme={null}
{ "error": { "type": "not_found", "message": "Workspace not found." } }
```

| Status | `type` |
| - | - |
| 400 | `invalid_request` |
| 401 | `unauthorized` |
| 403 | `forbidden`, `insufficient_scope` |
| 404 | `not_found` (also for workspaces you can't access) |
| 413 | `file_too_large` |
| 422 | `invalid_request` (a malformed body or parameter) |
| 429 | `rate_limited` (see `Retry-After`) |
| 5xx | `internal_error`, `agent_error`, `unavailable` |

## Pagination

Lists return `{ "data": [...], "has_more": true, "next_cursor": "..." }`. Pass `cursor=<next_cursor>` to get the next page, and `limit` to size them.

## Long operations

* **Uploads** return a job (`202`); follow it with `GET /v1/jobs/{job_id}` until `status` is `done`.
* **Ask** takes 10 to 120 seconds; stream its progress with `"stream": true`. See [Ask](/api/ask).

## Limits

* Ask: 60 questions per hour per user or key.
* Uploads: 20 files per request, 100 MB per file.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.