# ConusAI — full API surface

> Complete operation-level documentation of the Temps unified HTTP API.
> Generated from `contracts/openapi.json` by `scripts/docs/generate-llms.py`.
> Policy: `docs/architecture/ai-stack.md`.

## API overview

- OpenAPI version: `3.1.0`
- API title: ConusAI
- API version: `1.0.0`
- Total paths: 1052
- Total operations: 1273

## Paths

### `GET /.well-known/conusai-audit-keys.json`

- operationId: `get_audit_keys_jwks`
- summary: `GET /.well-known/conusai-audit-keys.json`: the checkpoint verifying keys
as a JWKS (D21). Keyless by design — a verifier in a customer's CI holds
no platform credential.
- tags: `Audit`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Checkpoint verifying keys (JWKS, RFC 8037 OKP/Ed25519)
    - `application/json`:
      - type: `object (1 properties)`
      - `keys` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`

### `GET /.well-known/conusai-obo-jwks.json`

- operationId: `jwks`
- tags: `Service gateway`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Public JWKS of the instance's assertion keys, EdDSA over Ed25519: the on-behalf-of keys (`conusai-obo-v<N>`, support spec §7) and the business service assertion keys (`conusai-business-v<N>`, ADR-050). For each, the signing key, the next one and, after a rotation, the previous one. A verifier uses only its own purpose's key ids. Cacheable for five minutes; a verifier refetches on an unknown kid.

### `GET /.well-known/conusai.json`

- operationId: `get_platform_info`
- summary: Get platform information
- tags: `Platform`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved platform information
    - `application/json`:
      - type: `object (3 properties)`
      - `architecture` *required*: `string`
        - description: System architecture (e.g., `"x86_64"`, "aarch64")
        - type: `string`
      - `os_type` *required*: `string`
        - description: Operating system type (e.g., "linux", "windows", "darwin")
        - type: `string`
      - `platforms` *required*: `array<string>`
        - description: List of supported platforms in "os/arch" format (e.g., ["linux/amd64"])
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /0/organizations/{org_slug}/chunk-upload/`

- operationId: `chunk_upload_options`
- summary: Chunk upload options (stub for sentry-cli compatibility).
- description: sentry-cli checks this endpoint to determine if chunk-based upload is supported.
We return a response indicating that chunk upload is NOT supported, which forces
sentry-cli to fall back to the standard file-by-file upload.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Chunk upload options
    - `application/json`:
      - type: `object (9 properties)`
      - `accept` *required*: `array<string>`
        - type: `array<string>`
      - `chunkSize` *required*: `integer`
        - type: `integer`
      - `chunksPerRequest` *required*: `integer`
        - type: `integer`
      - `compression` *required*: `array<string>`
        - type: `array<string>`
      - `concurrency` *required*: `integer`
        - type: `integer`
      - `hashAlgorithm` *required*: `string`
        - type: `string`
      - `maxFileSize` *required*: `integer`
        - type: `integer`
      - `maxRequestSize` *required*: `integer`
        - type: `integer`
      - `url` *required*: `string`
        - type: `string`

### `POST /0/organizations/{org_slug}/releases/`

- operationId: `create_release`
- summary: Create a release (stub for sentry-cli compatibility).
- description: sentry-cli calls this before uploading files. Since `ConusAI` implicitly creates
releases when source maps are uploaded, this is a no-op that returns the
expected response format.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `projects`: `array<string>`
      - description: Project slugs this release belongs to
      - type: `array<string>`
    - `version` *required*: `string`
      - description: Release version identifier
      - type: `string`
- responses:
  - `201`: Release created
    - `application/json`:
      - type: `object (5 properties)`
      - `dateCreated` *required*: `string`
        - type: `string`
      - `dateReleased`: `['string', 'null']`
        - type: `['string', 'null']`
      - `projects` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `shortVersion` *required*: `string`
        - type: `string`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized

### `POST /0/projects/{org_slug}/{project_slug}/releases/`

- operationId: `create_project_release`
- summary: Create a release for a specific project (stub for sentry-cli compatibility).
- description: sentry-cli calls this endpoint (instead of /organizations/.../releases/) when
both `SENTRY_ORG` and `SENTRY_PROJECT` env vars are set. Behaves identically to
the organizations endpoint but validates the project slug.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `projects`: `array<string>`
      - description: Project slugs this release belongs to
      - type: `array<string>`
    - `version` *required*: `string`
      - description: Release version identifier
      - type: `string`
- responses:
  - `201`: Release created
    - `application/json`:
      - type: `object (5 properties)`
      - `dateCreated` *required*: `string`
        - type: `string`
      - `dateReleased`: `['string', 'null']`
        - type: `['string', 'null']`
      - `projects` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `shortVersion` *required*: `string`
        - type: `string`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Project not found

### `PUT /0/projects/{org_slug}/{project_slug}/releases/{version}/`

- operationId: `finalize_project_release`
- summary: Finalize a release (stub for sentry-cli compatibility).
- description: sentry-cli calls `releases finalize` after uploading source maps. This sets
the dateReleased on the release. Since `ConusAI` stores source maps independently
of releases, this is a no-op that returns the expected response.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `version` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Release finalized
    - `application/json`:
      - type: `object (5 properties)`
      - `dateCreated` *required*: `string`
        - type: `string`
      - `dateReleased`: `['string', 'null']`
        - type: `['string', 'null']`
      - `projects` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `shortVersion` *required*: `string`
        - type: `string`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Project not found

### `GET /0/projects/{org_slug}/{project_slug}/releases/{version}/files/`

- operationId: `list_release_files`
- summary: List files for a release.
- description: Returns all source maps stored for a specific release in sentry-cli compatible format.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `version` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of release files
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `404`: Project not found

### `POST /0/projects/{org_slug}/{project_slug}/releases/{version}/files/`

- operationId: `upload_release_file`
- summary: Upload a source map file for a release.
- description: Accepts the same multipart format as the Sentry release files API.
The `name` field should be the URL path of the file (e.g., `~/dist/bundle.js.map`).

The route has a 50 MiB body limit applied at the router level (Fix #4).
A per-field size check provides an additional defense-in-depth layer.
- tags: `sentry-compat`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `version` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: File uploaded
    - `application/json`:
      - type: `object (7 properties)`
      - `dateCreated` *required*: `string`
        - type: `string`
      - `dist`: `['string', 'null']`
        - type: `['string', 'null']`
      - `headers` *required*: `any`
        - type: `any`
      - `id` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `sha1` *required*: `string`
        - type: `string`
      - `size` *required*: `integer`
        - type: `integer`
  - `400`: Bad request
  - `401`: Unauthorized
  - `404`: Project not found
  - `413`: Source map file exceeds the 50 MiB per-field limit

### `POST /_conusai/audit`

- operationId: `ingest`
- summary: `POST /api/_conusai/audit`: the keyless tenant endpoint (D5).
- tags: `Audit ingest`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `events` *required*: `array<object (16 properties)>`
      - description: The batch. At most 500 events; validation is all-or-nothing.
      - type: `array<object (16 properties)>`
    - `v`: `['integer', 'null']`
      - description: Contract version. Optional today, must be `1` when present; required
      - type: `['integer', 'null']`
- responses:
  - `202`: Accepted
    - `application/json`:
      - type: `object (3 properties)`
      - `accepted` *required*: `integer`
        - description: Events newly written.
        - type: `integer`
      - `duplicates` *required*: `integer`
        - description: Events skipped because their `event_id` was already stored.
        - type: `integer`
      - `redacted` *required*: `array<string>`
        - description: Paths of PII values replaced before hashing, e.g.
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not Found
  - `413`: Payload Too Large
  - `422`: Unprocessable Entity
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Too Many Requests

### `GET /_conusai/audit/events`

- operationId: `read_events`
- summary: `GET /_conusai/audit/events`: the events of the deployment token's own project
(showcase S4.4, D9). The token must hold `audit:read`; the organization and
the project come from the verified token, so a request cannot widen the read.
`app_tenant` and the resource filters only narrow it: the label is the app's
own and decides nothing here, so which tenant a person may see is the app's
check, made before it calls.
- tags: `Audit ingest`
- parameters:
  - `cursor` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `app_tenant` (query): `['string', 'null']`
  - `resource_type` (query): `['string', 'null']`
  - `resource_id` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `422`: Unprocessable Entity
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /_conusai/audit/subjects/erase`

- operationId: `erase_subject`
- summary: `POST /_conusai/audit/subjects/erase`: an app erases one of its subjects
(S8). The token must name `audit:erase`, and the organization and project
come from it, so the body can only choose a subject of the token's project.
The subject is in the body so that no request log holds the identifier. A
subject with nothing stored answers the same 204 and is created erased, so
the route is no oracle and a later event stores no details.
- tags: `Audit ingest`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `actor` *required*: `object (2 properties)`
      - description: A kind + id reference (delegators; primary targets keep their own type).
      - type: `object (2 properties)`
    - `app_tenant`: `['string', 'null']`
      - description: The app tenant its events named. An actor with no label on its events
      - type: `['string', 'null']`
- responses:
  - `204`: The subject's details are shredded; idempotent
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not Found
  - `422`: Unprocessable Entity
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Too Many Requests

### `POST /_conusai/envelope`

- operationId: `keyless_envelope`
- summary: `POST /api/_conusai/envelope`.
- tags: `Observe browser`
- parameters: _(none)_
- requestBody:
  - `application/x-sentry-envelope`:
    - type: `string`
- responses:
  - `200`: Accepted
  - `400`: The envelope is not valid
  - `403`: Origin not allowed for this host
  - `404`: No project on this host
  - `413`: Over the envelope size limit
  - `415`: Unsupported Content-Encoding
  - `429`: Visitor rate limit exceeded
  - `500`: The event could not be stored

### `POST /_conusai/event`

- operationId: `record_event_ingest`
- summary: Ingest a browser batch (v1).
- tags: `Metrics`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `string`
- responses:
  - `202`: Batch stored
    - `application/json`:
      - type: `object (1 properties)`
      - `accepted` *required*: `integer`
        - description: How many items were stored.
        - type: `integer`
  - `204`: Nothing to store (consent denied, or the host has no project)
  - `403`: Origin not allowed for this host
  - `404`: Host not in the route table
  - `413`: Body over 64 KiB
  - `415`: Unsupported Content-Encoding
  - `422`: The body is not a v1 batch (legacy shapes were removed) or does not match the v1 contract
  - `429`: Visitor rate limit exceeded
  - `500`: The batch could not be stored

### `POST /_conusai/identify`

- operationId: `identify`
- summary: `POST /api/_conusai/identify`.
- tags: `Observe browser`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `string`
- responses:
  - `204`: Written, or a no-op because consent is not granted
  - `403`: Origin not allowed for this host
  - `404`: No project on this host
  - `413`: Body over 64 KiB
  - `415`: Unsupported Content-Encoding
  - `422`: The body does not match the contract
  - `429`: Visitor rate limit exceeded

### `GET /_conusai/ids`

- operationId: `ids`
- summary: `GET /api/_conusai/ids`.
- tags: `Observe browser`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (9 properties)`
      - `environment`: `['string', 'null']`
        - type: `['string', 'null']`
      - `release`: `['string', 'null']`
        - description: The serving deployment's commit.
        - type: `['string', 'null']`
      - `replay` *required*: `object (3 properties)`
        - description: Replay bootstrap config (D12/D15).
        - type: `object (3 properties)`
      - `request_id` *required*: `string`
        - type: `string`
      - `session_id`: `['string', 'null']`
        - description: The canonical session UUID; absent when the request carries no valid
        - type: `['string', 'null']`
      - `session_sample_rate` *required*: `number`
        - description: `observe_settings.session_sample_rate`; wins over the SDK option (D4).
        - type: `number`
      - `trace_parent` *required*: `string`
        - description: `00-<trace id>-<parent id>-<flags>`, lower-case.
        - type: `string`
      - `trace_propagation_targets` *required*: `array<string>`
        - type: `array<string>`
      - `v` *required*: `integer`
        - description: Always `1`.
        - type: `integer`
  - `404`: Not Found

### `POST /_conusai/otlp/v1/logs`

- operationId: `browser_logs`
- summary: Ingest browser log records (OTLP/HTTP JSON or protobuf, keyless).
- tags: `OTel Ingest`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `string`
- responses:
  - `200`: Accepted; `{}` (JSON) or an empty ExportLogsServiceResponse (protobuf)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Origin not allowed for this host
  - `404`: No project on this host
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Body over 256 KiB or storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Visitor or project rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ingest saturated or log store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /_conusai/otlp/v1/traces`

- operationId: `browser_traces`
- summary: Ingest browser spans (OTLP/HTTP JSON or protobuf, keyless).
- tags: `OTel Ingest`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `string`
- responses:
  - `200`: Accepted; `{}` (JSON) or an empty ExportTraceServiceResponse (protobuf)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Origin not allowed for this host
  - `404`: No project on this host
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Body over 256 KiB or storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Visitor or project rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ingest saturated or span store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /_conusai/speed`

- operationId: `record_speed_ingest`
- summary: Ingest a browser web-vitals batch (v1).
- tags: `Performance`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `string`
- responses:
  - `202`: Batch stored
    - `application/json`:
      - type: `object (1 properties)`
      - `accepted` *required*: `integer`
        - description: How many items were stored.
        - type: `integer`
  - `204`: Nothing to store (consent denied, or the host has no project, environment and deployment)
  - `403`: Origin not allowed for this host
  - `404`: Host not in the route table
  - `413`: Body over 64 KiB
  - `415`: Unsupported Content-Encoding
  - `422`: The body is not a v1 batch (legacy shapes were removed) or does not match the v1 contract
  - `429`: Visitor rate limit exceeded
  - `500`: The batch could not be stored

### `GET /admin/billing/fx-rates`

- operationId: `listFxRates`
- tags: `Billing`
- parameters:
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Stored FX rates, newest first
    - `application/json`:
      - type: `object (1 properties)`
      - `rates` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Forbidden

### `POST /admin/billing/fx-rates`

- operationId: `createFxRate`
- tags: `Billing`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `base_currency` *required*: `string`
      - type: `string`
    - `effective_date` *required*: `string`
      - type: `string`
    - `quote_currency` *required*: `string`
      - type: `string`
    - `rate` *required*: `string`
      - description: A positive decimal string, e.g. `"0.8547"`. Never a float.
      - type: `string`
    - `source` *required*: `string`
      - description: Where the rate was taken from, e.g. `ECB euro reference rate 2026-10-01`.
      - type: `string`
- responses:
  - `201`: Rate appended
    - `application/json`:
      - type: `object (8 properties)`
      - `base_currency` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `effective_date` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `quote_currency` *required*: `string`
        - type: `string`
      - `rate` *required*: `string`
        - description: Decimal string, never a float.
        - type: `string`
      - `source` *required*: `string`
        - type: `string`
  - `400`: Invalid rate
  - `401`: Unauthorized
  - `403`: Forbidden
  - `409`: A rate for this pair and date already exists

### `GET /admin/billing/rates`

- operationId: `listBillingRates`
- tags: `Billing`
- parameters:
  - `page` (query): `integer`
  - `page_size` (query): `integer`
  - `plan_key` (query): `string`
  - `metric` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: One page of the rate catalog
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `rates` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `500`: Internal server error

### `POST /admin/billing/rates`

- operationId: `createBillingRate`
- tags: `Billing`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `currency` *required*: `string`
      - description: Three-letter ISO-4217 alphabetic code, e.g. `EUR`.
      - type: `string`
    - `effective_from`: `['string', 'null']`
      - description: When the rate takes effect. Defaults to now; must not be before the
      - type: `['string', 'null']`
    - `metric` *required*: `string`
      - description: One of `gb_hours`, `egress_gb`, `events`, `base_monthly`, or a
      - type: `string`
    - `plan_key` *required*: `string`
      - type: `string`
    - `unit_rate_minor` *required*: `integer`
      - description: Unit price in integer cents; must be non-negative.
      - type: `integer`
- responses:
  - `201`: Rate appended
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `currency` *required*: `string`
        - type: `string`
      - `effective_from` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `metric` *required*: `string`
        - type: `string`
      - `plan_key` *required*: `string`
        - type: `string`
      - `unit_rate_minor` *required*: `integer`
        - description: Unit price in integer cents. Never a float.
        - type: `integer`
  - `400`: Invalid rate
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Plan not found
  - `500`: Internal server error

### `GET /admin/feature-flags`

- operationId: `adminListFeatureFlags`
- summary: List all feature flags.
- tags: `Entitlements`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Feature flags listed
    - `application/json`:
      - type: `array<object (4 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /admin/feature-flags/{flag_key}`

- operationId: `adminUpdateFeatureFlag`
- summary: Update a feature flag and its overrides.
- tags: `Entitlements`
- parameters:
  - `flag_key` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `global_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `kill_switch`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `overrides`: `['array', 'null']`
      - type: `['array', 'null']`
- responses:
  - `200`: Feature flag updated
    - `application/json`:
      - type: `object (4 properties)`
      - `global_enabled` *required*: `boolean`
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `kill_switch` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /admin/gate-settings`

- operationId: `get_admin_gate`
- tags: `AdminGate`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Current admin gate config
    - `application/json`:
      - type: `object (5 properties)`
      - `allowed_hosts` *required*: `array<string>`
        - description: `Host` header values allowed. Empty = any host.
        - type: `array<string>`
      - `allowed_ips` *required*: `array<string>`
        - description: IPs / CIDRs allowed to reach the admin listener. Empty = any source.
        - type: `array<string>`
      - `editable` *required*: `boolean`
        - description: True when the config is writable through this API. False when env
        - type: `boolean`
      - `source` *required*: `string`
        - description: Where the active gate configuration came from. Env-supplied configs are
        - type: `string`
      - `trust_forwarded_for` *required*: `boolean`
        - description: When true, the gate trusts `X-Forwarded-For` from loopback peers.
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `PATCH /admin/gate-settings`

- operationId: `patch_admin_gate`
- tags: `AdminGate`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `allowed_hosts` *required*: `array<string>`
      - type: `array<string>`
    - `allowed_ips` *required*: `array<string>`
      - type: `array<string>`
    - `trust_forwarded_for` *required*: `boolean`
      - type: `boolean`
- responses:
  - `200`: Updated admin gate config
    - `application/json`:
      - type: `object (5 properties)`
      - `allowed_hosts` *required*: `array<string>`
        - description: `Host` header values allowed. Empty = any host.
        - type: `array<string>`
      - `allowed_ips` *required*: `array<string>`
        - description: IPs / CIDRs allowed to reach the admin listener. Empty = any source.
        - type: `array<string>`
      - `editable` *required*: `boolean`
        - description: True when the config is writable through this API. False when env
        - type: `boolean`
      - `source` *required*: `string`
        - description: Where the active gate configuration came from. Env-supplied configs are
        - type: `string`
      - `trust_forwarded_for` *required*: `boolean`
        - description: When true, the gate trusts `X-Forwarded-For` from loopback peers.
        - type: `boolean`
  - `400`: Invalid IP/CIDR/host
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `409`: Env-overridden or would lock out caller

### `GET /admin/metering/air-gap`

- operationId: `getAirGapConfig`
- tags: `Metering (Admin)`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Current air-gap SKU config
    - `application/json`:
      - type: `object (1 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Forbidden

### `PUT /admin/metering/air-gap`

- operationId: `setAirGapConfig`
- tags: `Metering (Admin)`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `enabled` *required*: `boolean`
      - type: `boolean`
- responses:
  - `200`: Air-gap SKU config updated
    - `application/json`:
      - type: `object (1 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Forbidden

### `GET /admin/metering/connectivity-grace`

- operationId: `getConnectivityGraceStatus`
- summary: Current connectivity-grace status for the admin banner (loop 13 Phase 3,
box133). Super-admin only; evaluating may emit an audit row and an admin
notification, but only when the state name actually changed since the last
evaluation — repeated reads of the same state are silent.
- tags: `Metering (Admin)`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Current connectivity grace state
    - `application/json`:
      - type: `object (2 properties) | object (3 properties) | object (2 properties)`
  - `401`: Unauthorized
  - `403`: Forbidden

### `POST /admin/metering/digest/run`

- operationId: `runMonthlyDigest`
- tags: `Billing`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: One digest pass completed
    - `application/json`:
      - type: `object (7 properties)`
      - `candidates` *required*: `integer`
        - description: Organizations with metered usage in the cycle and no ledger row yet, up
        - type: `integer`
      - `cycle_end` *required*: `string`
        - description: Exclusive end of that cycle.
        - type: `string`
      - `cycle_start` *required*: `string`
        - description: First instant of the closed cycle the digests report on.
        - type: `string`
      - `failed` *required*: `integer`
        - description: Claimed, but rendering or delivery failed. Logged at `error!`; never
        - type: `integer`
      - `sent` *required*: `integer`
        - description: Digests handed to the notification service.
        - type: `integer`
      - `skipped_already_claimed` *required*: `integer`
        - description: Claimed by a concurrent tick between the candidate query and the insert.
        - type: `integer`
      - `skipped_no_email_provider` *required*: `integer`
        - description: Claimed, but the organization has no enabled email provider, so there is
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `500`: Internal server error
  - `503`: No notification service is registered

### `GET /admin/metering/export.signed`

- operationId: `exportUsageSigned`
- summary: Download a signed, self-contained usage export for offline submission.
- description: # The signature is not a vendor signature

It is made with an installation-generated Ed25519 key (see
[`crate::signing`]) because the trust model
(docs/explanation/license-keys.md "Trust model") guarantees this
installation holds no
`ConusAI` private key. It proves payload **integrity** and **key continuity**,
not vendor-issued identity. The vendor binding is the license attestation
(claims + fingerprint); the raw license JWT is never included, per the same
raw-key hygiene. [`crate::export`] carries the offline `openssl` verification recipe.

# Available regardless of the air-gap toggle

TEL §6: exports are never blocked. The air-gap SKU suppresses *outbound*
egress, and this endpoint is the sanctioned alternative to egress, not an
instance of it — gating it on the toggle would leave an air-gapped operator
with no way to report usage at all.
- tags: `Metering (Admin)`
- parameters:
  - `start` (query): `['string', 'null']`
  - `end` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Signed usage export (RFC 7515 flattened JWS)
    - `application/json`:
      - type: `object (6 properties)`
      - `format` *required*: `string`
        - description: Always [`EXPORT_FORMAT`] — lets a recipient dispatch on file content
        - type: `string`
      - `license` *required*: `object (7 properties)`
        - description: The installed license, as attested inside an export.
        - type: `object (7 properties)`
      - `payload` *required*: `string`
        - description: base64url of `serde_json::to_vec(&ReportPayload)`.
        - type: `string`
      - `protected` *required*: `string`
        - description: base64url of the serialized [`JwsProtectedHeader`].
        - type: `string`
      - `public_key_pem` *required*: `string`
        - description: SPKI PEM of the installation public key, for offline verification.
        - type: `string`
      - `signature` *required*: `string`
        - description: base64url of the 64-byte Ed25519 signature over
        - type: `string`
  - `400`: Invalid report interval
  - `401`: Unauthorized
  - `403`: Forbidden

### `POST /admin/metering/reconcile`

- operationId: `reconcileUsageHours`
- tags: `Metering (Admin)`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Reconciliation completed
    - `application/json`:
      - type: `object (4 properties)`
      - `drift_count` *required*: `integer`
        - description: Total drifts found; `drifts` names at most the first 10.
        - type: `integer`
      - `drifts` *required*: `array<object (8 properties)>`
        - description: The first (at most 10) drifts, each with its full usage key.
        - type: `array<object (8 properties)>`
      - `hours_checked` *required*: `integer`
        - type: `integer`
      - `keys_checked` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden

### `POST /admin/metering/replay`

- operationId: `replayUsageHours`
- tags: `Metering (Admin)`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `end` *required*: `string`
      - description: Exclusive end hour in UTC.
      - type: `string`
    - `start` *required*: `string`
      - description: Inclusive start hour in UTC.
      - type: `string`
- responses:
  - `200`: Usage hours replayed
    - `application/json`:
      - type: `object (1 properties)`
      - `processed_hours` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden

### `GET /admin/metering/report-payload`

- operationId: `adminReportPayloadPreview`
- tags: `Metering (Admin)`
- parameters:
  - `start` (query): `['string', 'null']`
  - `end` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: The payload this installation would report
    - `application/json`:
      - type: `object (3 properties)`
      - `air_gap_enabled` *required*: `boolean`
        - description: Whether this installation is running under the air-gap SKU. When
        - type: `boolean`
      - `metering_endpoint` *required*: `string`
        - description: The resolved ingest endpoint payloads would be submitted to, shown so
        - type: `string`
      - `payload` *required*: `object (8 properties)`
        - description: Frozen v1 metering payload schema.
        - type: `object (8 properties)`
  - `400`: Invalid report interval
  - `401`: Unauthorized
  - `403`: Forbidden

### `GET /admin/oidc/providers`

- operationId: `list_oidc_providers`
- summary: Lists all configured OIDC providers, global and org-owned.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OIDC providers
    - `application/json`:
      - type: `array<object (13 properties)>`

### `POST /admin/oidc/providers`

- operationId: `create_oidc_provider`
- summary: Creates a new OIDC provider and records an audit log entry.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `client_id` *required*: `string`
      - type: `string`
    - `client_secret` *required*: `string`
      - type: `string`
    - `default_role`: `string`
      - type: `string`
    - `enabled`: `boolean`
      - type: `boolean`
    - `group_claim`: `string`
      - type: `string`
    - `issuer_url` *required*: `string`
      - type: `string`
    - `jit_provisioning`: `boolean`
      - type: `boolean`
    - `name` *required*: `string`
      - type: `string`
    - `role_claim`: `string`
      - type: `string`
    - `scopes`: `string`
      - type: `string`
    - `template`: `string`
      - type: `string`
    - `trust_idp_email`: `boolean`
      - description: Defaults false. Set to true only for `IdPs` where an admin
      - type: `boolean`
- responses:
  - `201`: OIDC provider created
    - `application/json`:
      - type: `object (13 properties)`
      - `client_id` *required*: `string`
        - type: `string`
      - `client_secret` *required*: `string`
        - description: Always masked — the secret is never returned after creation.
        - type: `string`
      - `default_role` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `group_claim` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `issuer_url` *required*: `string`
        - type: `string`
      - `jit_provisioning` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role_claim` *required*: `string`
        - type: `string`
      - `scopes` *required*: `string`
        - type: `string`
      - `template` *required*: `string`
        - type: `string`
      - `trust_idp_email` *required*: `boolean`
        - description: When true, the resolver skips the `email_verified` claim gate
        - type: `boolean`
  - `409`: Another OIDC provider already uses that name

### `PATCH /admin/oidc/providers/{provider_id}`

- operationId: `update_oidc_provider`
- summary: Updates an OIDC provider's configuration and records which fields
changed in the audit log.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `client_id`: `['string', 'null']`
      - type: `['string', 'null']`
    - `client_secret`: `['string', 'null']`
      - type: `['string', 'null']`
    - `default_role`: `['string', 'null']`
      - type: `['string', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `group_claim`: `['string', 'null']`
      - type: `['string', 'null']`
    - `issuer_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `jit_provisioning`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `role_claim`: `['string', 'null']`
      - type: `['string', 'null']`
    - `scopes`: `['string', 'null']`
      - type: `['string', 'null']`
    - `template`: `['string', 'null']`
      - type: `['string', 'null']`
    - `trust_idp_email`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
- responses:
  - `200`: OIDC provider updated
    - `application/json`:
      - type: `object (13 properties)`
      - `client_id` *required*: `string`
        - type: `string`
      - `client_secret` *required*: `string`
        - description: Always masked — the secret is never returned after creation.
        - type: `string`
      - `default_role` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `group_claim` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `issuer_url` *required*: `string`
        - type: `string`
      - `jit_provisioning` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role_claim` *required*: `string`
        - type: `string`
      - `scopes` *required*: `string`
        - type: `string`
      - `template` *required*: `string`
        - type: `string`
      - `trust_idp_email` *required*: `boolean`
        - description: When true, the resolver skips the `email_verified` claim gate
        - type: `boolean`

### `DELETE /admin/oidc/providers/{provider_id}`

- operationId: `delete_oidc_provider`
- summary: Deletes an OIDC provider, snapshotting its identity into the audit log
before removal.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: OIDC provider deleted

### `GET /admin/oidc/providers/{provider_id}/role-mappings`

- operationId: `list_oidc_role_mappings`
- summary: Lists the IdP-group-to-role mappings configured for an OIDC provider.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OIDC role mappings
    - `application/json`:
      - type: `array<object (5 properties)>`

### `POST /admin/oidc/providers/{provider_id}/role-mappings`

- operationId: `create_oidc_role_mapping`
- summary: Creates an IdP-group-to-role mapping for an OIDC provider and records
an audit log entry.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `idp_group` *required*: `string`
      - type: `string`
    - `priority` *required*: `integer`
      - type: `integer`
    - `role` *required*: `string`
      - type: `string`
- responses:
  - `201`: Role mapping created
    - `application/json`:
      - type: `object (5 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `idp_group` *required*: `string`
        - type: `string`
      - `priority` *required*: `integer`
        - type: `integer`
      - `provider_id` *required*: `integer`
        - type: `integer`
      - `role` *required*: `string`
        - type: `string`

### `POST /admin/oidc/providers/{provider_id}/test`

- operationId: `test_oidc_provider`
- summary: Tests connectivity to an OIDC provider's discovery/issuer endpoint and
reports success or the failure reason.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connection test result
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`

### `GET /admin/oidc/providers/{provider_id}/users`

- operationId: `list_oidc_provider_users`
- summary: Lists the users who have authenticated via the given OIDC provider.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Users authenticated via this OIDC provider
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `404`: Provider not found

### `DELETE /admin/oidc/role-mappings/{mapping_id}`

- operationId: `delete_oidc_role_mapping`
- summary: Deletes an OIDC role mapping and records an audit log entry.
- tags: `Authentication`
- parameters:
  - `mapping_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Role mapping deleted

### `GET /admin/onboarding-links`

- operationId: `list_onboarding_links`
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /admin/onboarding-links`

- operationId: `create_onboarding_link`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `expires_in_days`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `intended_email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `quota_max_containers`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `quota_max_disk_mb`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `quota_max_projects`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `suggested_org_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `suggested_workspace_name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (10 properties)`
      - `delivery_status` *required*: `string`
        - type: `string`
      - `expires_at` *required*: `string`
        - type: `string`
      - `intended_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `link_url` *required*: `string`
        - type: `string`
      - `revoked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `suggested_org_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `suggested_workspace_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `token_hash` *required*: `string`
        - type: `string`
      - `used_at`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /admin/onboarding-links/{token_hash}/revoke`

- operationId: `revoke_onboarding_link`
- tags: `Organizations`
- parameters:
  - `token_hash` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `text/plain`:
      - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /admin/organizations`

- operationId: `list_admin_organizations`
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /admin/organizations/{org_id}/ocr-limits`

- operationId: `adminGetOrganizationOcrLimits`
- summary: Read the OCR limits an organization is enforced against.
- tags: `Entitlements`
- parameters:
  - `org_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Enforced OCR limits
    - `application/json`:
      - type: `object (8 properties)`
      - `allowed_tiers` *required*: `array<string>`
        - type: `array<string>`
      - `async_max_bytes` *required*: `integer`
        - description: The enforced async-job document size ceiling, in bytes.
        - type: `integer`
      - `async_max_pages` *required*: `integer`
        - description: The enforced async-job page-count ceiling.
        - type: `integer`
      - `max_table_templates`: `['integer', 'null']`
        - description: The enforced cap on confirmed table templates; `null` when the plan sets none.
        - type: `['integer', 'null']`
      - `ocr_fair_share_weight` *required*: `integer`
        - type: `integer`
      - `ocr_pages_in_flight` *required*: `integer`
        - description: Burst pages in flight (Free 25, Pro 100, Enterprise 300 unless overridden).
        - type: `integer`
      - `ocr_pages_in_flight_ceiling` *required*: `integer`
        - description: Maximum override from configured replicas × two slots × 50 pages.
        - type: `integer`
      - `overridden` *required*: `object (6 properties)`
        - description: Which OCR limits the organization overrides itself.
        - type: `object (6 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /admin/organizations/{org_id}/ocr-limits`

- operationId: `adminSetOrganizationOcrLimits`
- summary: Change the OCR limit overrides of an organization. Only fields present in the body change.
- tags: `Entitlements`
- parameters:
  - `org_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `allowed_tiers`: `['array', 'null']`
      - type: `['array', 'null']`
    - `async_max_bytes`: `['integer', 'null']`
      - description: Document size ceiling in bytes, 1 to 524288000 (500 MiB).
      - type: `['integer', 'null']`
    - `async_max_pages`: `['integer', 'null']`
      - description: Page-count ceiling, 1 to 5000.
      - type: `['integer', 'null']`
    - `max_table_templates`: `['integer', 'null']`
      - description: Confirmed table templates per organization, at least 1.
      - type: `['integer', 'null']`
    - `ocr_fair_share_weight`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `ocr_pages_in_flight`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: Limits updated; the enforced limits follow
    - `application/json`:
      - type: `object (8 properties)`
      - `allowed_tiers` *required*: `array<string>`
        - type: `array<string>`
      - `async_max_bytes` *required*: `integer`
        - description: The enforced async-job document size ceiling, in bytes.
        - type: `integer`
      - `async_max_pages` *required*: `integer`
        - description: The enforced async-job page-count ceiling.
        - type: `integer`
      - `max_table_templates`: `['integer', 'null']`
        - description: The enforced cap on confirmed table templates; `null` when the plan sets none.
        - type: `['integer', 'null']`
      - `ocr_fair_share_weight` *required*: `integer`
        - type: `integer`
      - `ocr_pages_in_flight` *required*: `integer`
        - description: Burst pages in flight (Free 25, Pro 100, Enterprise 300 unless overridden).
        - type: `integer`
      - `ocr_pages_in_flight_ceiling` *required*: `integer`
        - description: Maximum override from configured replicas × two slots × 50 pages.
        - type: `integer`
      - `overridden` *required*: `object (6 properties)`
        - description: Which OCR limits the organization overrides itself.
        - type: `object (6 properties)`
  - `400`: A value is outside its range (urn:conusai:ocr:limit-out-of-range)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /admin/organizations/{org_id}/plan`

- operationId: `adminUpdateOrganizationPlan`
- summary: Assign a plan to an organization.
- tags: `Entitlements`
- parameters:
  - `org_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `plan_key` *required*: `string`
      - type: `string`
- responses:
  - `200`: Organization plan updated
    - `application/json`:
      - type: `object (2 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /admin/organizations/{org_id}/restore`

- operationId: `restore_organization`
- tags: `Organizations`
- parameters:
  - `org_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /admin/organizations/{org_id}/suspend`

- operationId: `suspend_organization`
- tags: `Organizations`
- parameters:
  - `org_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /admin/plans`

- operationId: `adminListPlans`
- summary: List all plans in the catalog.
- tags: `Entitlements`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Plans listed
    - `application/json`:
      - type: `array<object (6 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /admin/plans`

- operationId: `adminCreatePlan`
- summary: Create a new plan.
- tags: `Entitlements`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `allowances` *required*: `object (8 properties)`
      - description: Usage-metering allowances stored in `plans.allowances`.
      - type: `object (8 properties)`
    - `capabilities` *required*: `object (24 properties)`
      - description: Capability matrix stored in `plans.capabilities`.
      - type: `object (24 properties)`
    - `key` *required*: `string`
      - type: `string`
    - `limits` *required*: `object (33 properties)`
      - description: Resource limits stored in `plans.limits`. Unset count quotas are unlimited;
      - type: `object (33 properties)`
    - `name` *required*: `string`
      - type: `string`
- responses:
  - `201`: Plan created
    - `application/json`:
      - type: `object (6 properties)`
      - `allowances` *required*: `object (8 properties)`
        - description: Usage-metering allowances stored in `plans.allowances`.
        - type: `object (8 properties)`
      - `capabilities` *required*: `object (24 properties)`
        - description: Capability matrix stored in `plans.capabilities`.
        - type: `object (24 properties)`
      - `key` *required*: `string`
        - type: `string`
      - `limits` *required*: `object (33 properties)`
        - description: Resource limits stored in `plans.limits`. Unset count quotas are unlimited;
        - type: `object (33 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `resource_ceiling`: `object (4 properties)`
        - description: The CPU and memory one container of an organisation on a plan may use,
        - type: `object (4 properties)`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /admin/plans/{plan_key}`

- operationId: `adminUpdatePlan`
- summary: Update an existing plan.
- tags: `Entitlements`
- parameters:
  - `plan_key` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `allowances`: `object (8 properties) | null`
      - type: `object (8 properties) | null`
    - `capabilities`: `object (24 properties) | null`
      - type: `object (24 properties) | null`
    - `limits`: `object (33 properties) | null`
      - type: `object (33 properties) | null`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Plan updated
    - `application/json`:
      - type: `object (6 properties)`
      - `allowances` *required*: `object (8 properties)`
        - description: Usage-metering allowances stored in `plans.allowances`.
        - type: `object (8 properties)`
      - `capabilities` *required*: `object (24 properties)`
        - description: Capability matrix stored in `plans.capabilities`.
        - type: `object (24 properties)`
      - `key` *required*: `string`
        - type: `string`
      - `limits` *required*: `object (33 properties)`
        - description: Resource limits stored in `plans.limits`. Unset count quotas are unlimited;
        - type: `object (33 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `resource_ceiling`: `object (4 properties)`
        - description: The CPU and memory one container of an organisation on a plan may use,
        - type: `object (4 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /admin/usage`

- operationId: `adminUsageTotals`
- tags: `Usage (Admin)`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Per-org current-cycle totals
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `403`: Forbidden

### `POST /agents/webhook/{webhook_id}`

- operationId: `webhook_trigger`
- summary: Public webhook endpoint. Authenticated via `X-Webhook-Token` header.
- description: `POST /api/agents/webhook/{webhook_id}`
Header: `X-Webhook-Token: <secret>`

The `webhook_id` in the URL is a short non-secret identifier (safe to log).
The actual credential is the secret token in the header.

Accepts any JSON body, which is passed as `user_context` to the agent run.
- tags: `Agents`
- parameters:
  - `webhook_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `202`: Agent run created
    - `application/json`:
      - type: `object (2 properties)`
      - `run_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Missing or invalid X-Webhook-Token header
  - `404`: Invalid webhook ID
  - `422`: Agent disabled

### `GET /ai/conversations`

- operationId: `list_all_conversations`
- summary: List every active conversation across all projects, most-recently-active
first, annotated with project name/slug. Powers the unified "all chats"
switcher in the AI assistant dock.
- tags: `AI Chat`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
  - `403`: Forbidden

### `GET /ai/pricing`

- operationId: `get_pricing`
- tags: `AI Gateway Pricing`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Model pricing information
    - `application/json`:
      - type: `object (1 properties)`
      - `models` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /ai/providers/test`

- operationId: `test_provider_key_inline`
- tags: `AI Gateway Admin`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `api_key` *required*: `string`
      - description: The raw API key to test
      - type: `string`
    - `base_url`: `['string', 'null']`
      - description: Optional custom base URL
      - type: `['string', 'null']`
    - `provider` *required*: `string`
      - description: Provider ID: "openai", "anthropic", "xai", "gemini"
      - type: `string`
- responses:
  - `200`: Test result
    - `application/json`:
      - type: `object (4 properties)`
      - `error`: `['string', 'null']`
        - description: Error message if the test failed
        - type: `['string', 'null']`
      - `latency_ms` *required*: `integer`
        - description: Response time in milliseconds
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /ai/v1/chat/completions`

- operationId: `chat_completions`
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `200`: Chat completion response
    - `application/json`:
      - type: `object (7 properties)`
      - `choices` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `created` *required*: `integer`
        - type: `integer`
      - `id` *required*: `string`
        - type: `string`
      - `model` *required*: `string`
        - type: `string`
      - `object` *required*: `string`
        - type: `string`
      - `provenance`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `usage`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `404`: Model not found
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `500`: Internal error
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`

### `POST /ai/v1/embeddings`

- operationId: `embeddings`
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `dimensions`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `encoding_format`: `['string', 'null']`
      - type: `['string', 'null']`
    - `input` *required*: `string | array<string>`
      - type: `string | array<string>`
    - `input_type`: `['string', 'null']`
      - description: Which side of an asymmetric model the input is: `passage` (the
      - type: `['string', 'null']`
    - `model` *required*: `string`
      - type: `string`
- responses:
  - `200`: Embedding response
    - `application/json`:
      - type: `object (4 properties)`
      - `data` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `model` *required*: `string`
        - type: `string`
      - `object` *required*: `string`
        - type: `string`
      - `usage` *required*: `object (2 properties)`
        - type: `object (2 properties)`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `404`: Model not found
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`

### `POST /ai/v1/messages`

- operationId: `agent_messages`
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `any`
  - `400`: Bad Request
  - `403`: Forbidden
  - `503`: Service Unavailable

### `GET /ai/v1/models`

- operationId: `list_models`
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of available models
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `object` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`

### `POST /ai/v1/rerank`

- operationId: `rerank`
- summary: Rerank documents against a query with a local cross-encoder.
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `documents` *required*: `array<string>`
      - description: At most 100; query and documents together at most 1 MiB.
      - type: `array<string>`
    - `model` *required*: `string`
      - description: The local reranker build this host loaded, such as
      - type: `string`
    - `query` *required*: `string`
      - type: `string`
    - `top_n`: `['integer', 'null']`
      - description: How many results to return, 1 to 100; default every document. A value
      - type: `['integer', 'null']`
- responses:
  - `200`: Documents ordered by relevance
    - `application/json`:
      - type: `object (4 properties)`
      - `model` *required*: `string`
        - type: `string`
      - `object` *required*: `string`
        - description: Always `list`.
        - type: `string`
      - `results` *required*: `array<object (2 properties)>`
        - description: The `top_n` best documents, highest `relevance_score` first; ties keep
        - type: `array<object (2 properties)>`
      - `usage` *required*: `object (2 properties)`
        - type: `object (2 properties)`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `402`: Spend cap reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Permission or model allow-list refusal
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `404`: Reranker not enabled on this instance
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `429`: Local compute busy or rate limited; see Retry-After
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`
  - `503`: Local compute timed out; see Retry-After
    - `application/json`:
      - type: `object (1 properties)`
      - `error` *required*: `object (5 properties)`
        - type: `object (5 properties)`

### `POST /ai/v1/responses`

- operationId: `agent_responses`
- tags: `AI Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `any`
  - `400`: Bad Request
  - `403`: Forbidden
  - `503`: Service Unavailable

### `GET /asn/{ip}`

- operationId: `get_asn`
- summary: Get ASN and network-type information for an IP address
- tags: `geo`
- parameters:
  - `ip` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: ASN information retrieved
    - `application/json`:
      - type: `any`
  - `400`: Invalid IP address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Authentication required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /audit/logs`

- operationId: `listPlatformAuditLogs`
- summary: List audit logs with optional filtering
- tags: `Audit Logs`
- parameters:
  - `operation_type` (query): `string`
  - `user_id` (query): `integer`
  - `from` (query): `string`
  - `to` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of audit logs
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /auth/cli/device/approve`

- operationId: `cli_device_approve`
- summary: Approves a pending CLI device-login session for the authenticated user,
mints a scoped API key, and stashes it (encrypted) for the CLI to claim
on its next poll.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `user_code` *required*: `string`
      - type: `string`
- responses:
  - `200`: Session approved; CLI can now claim the API key
    - `application/json`:
      - type: `object (2 properties)`
      - `status` *required*: `string`
        - type: `string`
      - `user_code` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Browser session required, or the approver is not a member of the organization the CLI requested
  - `404`: Unknown user_code
  - `409`: Already resolved
  - `410`: Session expired
  - `428`: Recent MFA verification required
  - `500`: Internal server error

### `POST /auth/cli/device/deny`

- operationId: `cli_device_deny`
- summary: Denies a pending CLI device-login session for the authenticated user.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `user_code` *required*: `string`
      - type: `string`
- responses:
  - `200`: Session denied
    - `application/json`:
      - type: `object (2 properties)`
      - `status` *required*: `string`
        - type: `string`
      - `user_code` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Unknown user_code
  - `409`: Already resolved
  - `410`: Session expired
  - `500`: Internal server error

### `GET /auth/cli/device/lookup`

- operationId: `cli_device_lookup`
- summary: Looks up a CLI device-login session by its user-facing code so the web
UI can display who/what is requesting authorization.
- tags: `Authentication`
- parameters:
  - `user_code` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Device session metadata
    - `application/json`:
      - type: `object (8 properties)`
      - `client_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `organization`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `organization_error`: `['string', 'null']`
        - description: Why approval would be refused for the signed-in user (e.g. not a
        - type: `['string', 'null']`
      - `requested_ip`: `['string', 'null']`
        - type: `['string', 'null']`
      - `requested_organization_slug`: `['string', 'null']`
        - description: Slug the CLI asked for with `--org`, if any. Echoed even when the
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: `pending` | `approved` | `denied` | `expired`.
        - type: `string`
      - `user_code` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Unknown user_code
  - `410`: Device session expired
  - `500`: Internal server error

### `POST /auth/cli/device/poll`

- operationId: `cli_device_poll`
- summary: Polls a CLI device-login session for its current status, enforcing
minimum poll spacing and delivering the minted API key once approved.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `device_code` *required*: `string`
      - type: `string`
- responses:
  - `200`: Poll result; check `status` field
    - `application/json`:
      - type: `object (1 properties) | object (1 properties) | object (1 properties) | object (1 properties) | object (8 properties)`
  - `404`: Unknown device_code
  - `500`: Internal server error

### `POST /auth/cli/device/start`

- operationId: `cli_device_start`
- summary: Creates a new pending CLI device-login session with a fresh device/user
code pair, retrying on the rare code collision.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `client_name`: `['string', 'null']`
      - description: Friendly hostname / client identifier shown in the browser approval
      - type: `['string', 'null']`
    - `organization_slug`: `['string', 'null']`
      - description: Slug of the organization the CLI wants its key bound to
      - type: `['string', 'null']`
- responses:
  - `200`: Device session created
    - `application/json`:
      - type: `object (6 properties)`
      - `device_code` *required*: `string`
        - description: Opaque secret the CLI polls with. Never display to a human.
        - type: `string`
      - `expires_in` *required*: `integer`
        - description: Seconds until the `device_code` expires.
        - type: `integer`
      - `interval` *required*: `integer`
        - description: Suggested polling interval, in seconds.
        - type: `integer`
      - `user_code` *required*: `string`
        - description: Short human-readable code the user types into the browser.
        - type: `string`
      - `verification_uri` *required*: `string`
        - description: Base verification URL — the CLI may display this when the
        - type: `string`
      - `verification_uri_complete` *required*: `string`
        - description: `verification_uri` with `user_code` pre-filled. Open this directly.
        - type: `string`
  - `400`: Malformed organization_slug
  - `500`: Internal server error

### `POST /auth/cli/logout`

- operationId: `cli_logout`
- summary: Revokes the bearer API key the CLI is currently presenting and writes an
audit record; requires API key authentication.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `204`: API key revoked
  - `401`: Not authenticated
  - `403`: Endpoint requires API key authentication
  - `500`: Internal server error

### `GET /auth/email-status`

- operationId: `email_status`
- summary: Reports whether email-based auth flows (magic link, password reset) and
which OIDC providers are available, so the login page can render the
right options.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Email configuration status
    - `application/json`:
      - type: `object (4 properties)`
      - `email_configured` *required*: `boolean`
        - type: `boolean`
      - `magic_link_available` *required*: `boolean`
        - type: `boolean`
      - `oidc_providers` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `password_reset_available` *required*: `boolean`
        - type: `boolean`
  - `500`: Internal server error

### `POST /auth/login`

- operationId: `login`
- summary: Authenticates a user by email and password, starting an MFA challenge or
creating a session cookie depending on the account's MFA enrollment.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email` *required*: `string`
      - type: `string`
    - `password` *required*: `string`
      - type: `string`
- responses:
  - `200`: Login successful, session cookie set
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Invalid credentials, or the account's role requires MFA enrollment that has not been completed
  - `500`: Internal server error

### `POST /auth/logout/all`

- operationId: `logout_all`
- summary: Signs the user out of **every** session they have, on every device — the
explicit all-sessions counterpart to [`logout`] (Decision D8, review
F-6-30).
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully logged out of all sessions
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /auth/magic-link/request`

- operationId: `request_magic_link`
- summary: Sends a magic-link login email if the address matches an account; always
reports success to avoid leaking whether the email is registered.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `email` *required*: `string`
      - type: `string`
- responses:
  - `200`: Magic link sent if email exists
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Bad request
  - `503`: Email service not configured

### `GET /auth/magic-link/verify`

- operationId: `verify_magic_link`
- summary: Verifies a magic-link token and, on success, creates a session for the
associated user.
- tags: `Authentication`
- parameters:
  - `token` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Magic link verified, session cookie set
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid or expired token
  - `500`: Internal server error

### `GET /auth/oidc/callback`

- operationId: `oidc_callback`
- summary: Handles the `IdP` redirect back from a global OIDC provider, completing
login and setting the session cookie, or redirecting to the login page
with an opaque error code on failure.
- tags: `Authentication`
- parameters:
  - `code` (query): `['string', 'null']`
  - `state` (query): `['string', 'null']`
  - `error` (query): `['string', 'null']`
  - `error_description` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to app with session cookie or login error

### `GET /auth/oidc/login/{slug}`

- operationId: `start_oidc_login_by_slug`
- summary: Starts the login flow for the OIDC provider identified by `slug`,
redirecting the browser to the `IdP`'s authorize URL.
- tags: `Authentication`
- parameters:
  - `slug` (path) *required*: `string`
  - `return_to` (query): `['string', 'null']`
  - `reauthenticate` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to IdP authorize URL
  - `400`: `reauthenticate` is not `account`
  - `401`: `reauthenticate=account` without a browser session
  - `404`: Provider not found
  - `409`: `reauthenticate=account`: the account has MFA (`step-up-use-second-factor`) or the session did not sign in through this provider
  - `503`: OIDC provider unreachable

### `GET /auth/oidc/org/callback`

- operationId: `org_oidc_callback`
- summary: \[conusai\] Phase 4a: org-aware OIDC callback. Resolves the user via
`resolve_org_user`, which provisions org membership without ever touching
global roles.
- tags: `Authentication`
- parameters:
  - `code` (query): `['string', 'null']`
  - `state` (query): `['string', 'null']`
  - `error` (query): `['string', 'null']`
  - `error_description` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to app with session cookie or login error

### `GET /auth/oidc/org/login/{provider_id}`

- operationId: `start_org_oidc_login`
- summary: \[conusai\] Phase 4a: initiate login through an org-owned OIDC provider.
Registered in `handlers.rs` inside the rate-limited `/auth/*` router group.
- tags: `Authentication`
- parameters:
  - `provider_id` (path) *required*: `integer`
  - `return_to` (query): `['string', 'null']`
  - `reauthenticate` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to IdP authorize URL
  - `400`: `reauthenticate` is not `account`
  - `401`: `reauthenticate=account` without a browser session
  - `404`: Provider not found or not org-owned
  - `409`: `reauthenticate=account`: the account has MFA (`step-up-use-second-factor`) or the session did not sign in through this provider
  - `503`: OIDC provider unreachable

### `POST /auth/oidc/org/route`

- operationId: `org_sso_route`
- summary: \[conusai\] Phase 4b: route an email/domain to an org-owned OIDC provider.
The response is identical whether the user exists or not; only the domain
matters, and the endpoint is registered inside the rate-limited `/auth/*`
router group in `handlers.rs`.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `email` *required*: `string`
      - type: `string`
- responses:
  - `200`: Routing decision
    - `application/json`:
      - type: `object (1 properties)`
      - `redirect_url`: `['string', 'null']`
        - type: `['string', 'null']`

### `GET /auth/oidc/providers`

- operationId: `list_public_providers`
- summary: Lists the OIDC providers enabled for the public login page.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Enabled OIDC providers for login page
    - `application/json`:
      - type: `object (1 properties)`
      - `providers` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`

### `POST /auth/password-reset/request`

- operationId: `request_password_reset`
- summary: Sends a password-reset email if the address matches an account; always
reports success to avoid leaking whether the email is registered.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `email` *required*: `string`
      - type: `string`
- responses:
  - `200`: Reset email sent if account exists
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `503`: Email service not configured

### `POST /auth/password-reset/verify`

- operationId: `reset_password`
- summary: Consumes a password-reset token to set a new password and records an audit log.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `new_password` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - type: `string`
- responses:
  - `200`: Password reset successful
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid or expired token
  - `500`: Internal server error

### `GET /auth/sso/start`

- operationId: `sso_start`
- summary: Start the console → git-host SSO handshake. See the module docs for the
checks; every failure is a 403 (401 only when there is no session at
all, from the `RequireAuth` extractor).
- tags: `Authentication`
- parameters:
  - `return` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to the git host's SSO callback carrying a short-lived ticket
  - `401`: No session
  - `403`: Not a browser session, malformed return URL, unknown host, not a member of the owning organisation, or SSO disabled for the service

### `POST /auth/step-up`

- operationId: `verify_step_up`
- summary: Re-verify the caller's second factor and elevate **this** session for
[`crate::STEP_UP_TTL_MINUTES`].
- description: # What this endpoint does and does not grant

It grants nothing to the caller directly: there is no token in the
response. It writes `step_up_expires_at` on the one `sessions` row the
request authenticated with, which the sensitive-action policy then reads.
A caller cannot aim it at another session — the id comes from the verified
auth context, never from the body — and cannot elevate a credential class
that has no session row at all (API keys, CLI tokens, deployment tokens all
get 403 here).

# Rate limiting

Two layers. The route group's per-IP limiter is the outer one; this handler
adds a per-`(user, session)` budget because a six-digit TOTP is brute-forcible
in ~10^6 guesses and an attacker holding a stolen cookie can trivially
rotate source addresses. Rate-limited attempts are audited: a burst of them
is what a cookie-theft attack looks like from the server.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `code` *required*: `string`
      - description: Current TOTP value, or an unused recovery code. A credential: never
      - type: `string`
- responses:
  - `200`: Session elevated for sensitive actions
    - `application/json`:
      - type: `object (1 properties)`
      - `expires_at` *required*: `string`
        - description: ISO 8601 instant after which sensitive actions require verification
        - type: `string`
  - `400`: Verification code is empty
  - `401`: Invalid code, or the session is no longer active
  - `403`: Browser session required
  - `428`: MFA setup required before verification is possible
  - `429`: Too many verification attempts
  - `500`: Verification infrastructure failed

### `POST /auth/step-up/password`

- operationId: `verify_password_step_up`
- summary: Re-enter the account's password to exercise the person's own account
rights (export, self-delete) without a second factor (M-wave F8, ADR-068).
- description: Writes the narrower `account_step_up_expires_at` on this session for
[`crate::STEP_UP_TTL_MINUTES`], which only those two actions read: every
other sensitive action still needs MFA. An account with MFA enrolled gets
409 `step-up-use-second-factor` and verifies with its code instead. Shares
the per-session budget of `POST /auth/step-up`, so a wrong password counts
against it; the attempt is audited with its method, never its value.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `password` *required*: `string`
      - description: The account's password. A credential: never logged, never echoed
      - type: `string`
- responses:
  - `200`: Session may export or delete its own account until `expires_at`
    - `application/json`:
      - type: `object (1 properties)`
      - `expires_at` *required*: `string`
        - description: ISO 8601 instant after which sensitive actions require verification
        - type: `string`
  - `400`: Password is empty
  - `401`: Wrong password, or the session is no longer active
  - `403`: Browser session required
  - `409`: The account has MFA (`step-up-use-second-factor`) or no password (`step-up-password-not-set`)
  - `429`: Too many verification attempts
  - `500`: Verification infrastructure failed

### `GET /auth/verify-email`

- operationId: `verify_email`
- summary: Consumes an email-verification token to mark the associated user's
email as verified and records an audit log.
- tags: `Authentication`
- parameters:
  - `token` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Email verified successfully
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid or expired token
  - `500`: Internal server error

### `POST /auth/verify-email/resend`

- operationId: `resend_verification_email`
- summary: Resends the verification email if the address matches an unverified
account; always reports success to avoid leaking whether the email is
registered.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `email` *required*: `string`
      - type: `string`
- responses:
  - `200`: Resend verification email sent if account exists and is unverified
    - `application/json`:
      - type: `object (4 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `mfa_required` *required*: `boolean`
        - type: `boolean`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `503`: Email service not configured

### `POST /auth/verify-mfa`

- operationId: `verify_mfa_challenge`
- summary: Verifies the MFA code against the pending MFA session cookie and, on
success, completes login.
- tags: `Authentication`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `code` *required*: `string`
      - type: `string`
- responses:
  - `204`: MFA verification successful
  - `400`: Invalid request
  - `401`: Invalid MFA code
  - `500`: Internal server error

### `GET /billing/pricing`

- operationId: `publicPricing`
- tags: `Billing`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Plan catalog and current list rates
    - `application/json`:
      - type: `object (2 properties)`
      - `plans` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `rates` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `500`: Internal server error

### `GET /blob`

- operationId: `blob_list`
- summary: List blobs
- tags: `Blob`
- parameters:
  - `limit` (query): `integer`
  - `prefix` (query): `string`
  - `cursor` (query): `string`
  - `project_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of blobs
    - `application/json`:
      - type: `object (3 properties)`
      - `blobs` *required*: `array<object (5 properties)>`
        - description: List of blobs
        - type: `array<object (5 properties)>`
      - `cursor`: `['string', 'null']`
        - description: Continuation token for next page
        - type: `['string', 'null']`
      - `hasMore` *required*: `boolean`
        - description: Whether there are more results
        - type: `boolean`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /blob`

- operationId: `blob_put`
- summary: Upload a blob
- tags: `Blob`
- parameters:
  - `pathname` (query): `string`
  - `content_type` (query): `string`
  - `add_random_suffix` (query): `boolean`
  - `project_id` (query): `integer`
- requestBody:
  - `application/octet-stream`:
    - type: `string`
- responses:
  - `201`: Blob uploaded successfully
    - `application/json`:
      - type: `object (5 properties)`
      - `contentType` *required*: `string`
        - description: Content type of the blob
        - type: `string`
      - `pathname` *required*: `string`
        - description: Original pathname
        - type: `string`
      - `size` *required*: `integer`
        - description: Size in bytes
        - type: `integer`
      - `uploadedAt` *required*: `string`
        - description: Upload timestamp
        - type: `string`
      - `url` *required*: `string`
        - description: URL path to access the blob
        - type: `string`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /blob`

- operationId: `blob_delete`
- summary: Delete blobs
- tags: `Blob`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `pathnames` *required*: `array<string>`
      - description: Pathnames to delete (relative to project)
      - type: `array<string>`
    - `projectId`: `['integer', 'null']`
      - description: Project ID (required for API key/session auth, optional for deployment tokens)
      - type: `['integer', 'null']`
- responses:
  - `200`: Blobs deleted successfully
    - `application/json`:
      - type: `object (1 properties)`
      - `deleted` *required*: `integer`
        - description: Number of blobs deleted
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /blob/copy`

- operationId: `blob_copy`
- summary: Copy a blob to a new location
- tags: `Blob`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `fromUrl` *required*: `string`
      - description: Source blob URL or pathname
      - type: `string`
    - `projectId`: `['integer', 'null']`
      - description: Project ID (required for API key/session auth, optional for deployment tokens)
      - type: `['integer', 'null']`
    - `toPathname` *required*: `string`
      - description: Destination pathname
      - type: `string`
- responses:
  - `200`: Blob copied successfully
    - `application/json`:
      - type: `object (5 properties)`
      - `contentType` *required*: `string`
        - description: Content type of the blob
        - type: `string`
      - `pathname` *required*: `string`
        - description: Original pathname
        - type: `string`
      - `size` *required*: `integer`
        - description: Size in bytes
        - type: `integer`
      - `uploadedAt` *required*: `string`
        - description: Upload timestamp
        - type: `string`
      - `url` *required*: `string`
        - description: URL path to access the blob
        - type: `string`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Source blob not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /blob/disable`

- operationId: `blob_disable`
- summary: Disable Blob service
- tags: `Blob Management`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Blob service disabled
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - description: Human-readable message
        - type: `string`
      - `success` *required*: `boolean`
        - description: Whether the operation succeeded
        - type: `boolean`
  - `401`: Unauthorized
  - `404`: Blob service not enabled
  - `500`: Internal server error

### `POST /blob/enable`

- operationId: `blob_enable`
- summary: Enable Blob service
- tags: `Blob Management`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `docker_image`: `['string', 'null']`
      - description: Docker image to use (optional, defaults to `RustFS`)
      - type: `['string', 'null']`
    - `root_password`: `['string', 'null']`
      - description: Root password for S3 access
      - type: `['string', 'null']`
    - `root_user`: `['string', 'null']`
      - description: Root user for S3 access
      - type: `['string', 'null']`
- responses:
  - `200`: Blob service enabled
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Human-readable message
        - type: `string`
      - `status` *required*: `object (4 properties)`
        - description: Response for Blob service status
        - type: `object (4 properties)`
      - `success` *required*: `boolean`
        - description: Whether the operation succeeded
        - type: `boolean`
  - `401`: Unauthorized
  - `500`: Internal server error

### `PATCH /blob/update`

- operationId: `blob_update`
- summary: Update Blob service configuration
- tags: `Blob Management`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `docker_image`: `['string', 'null']`
      - description: Docker image to use (defaults to the platform's mirrored `RustFS`;
      - type: `['string', 'null']`
- responses:
  - `200`: Blob service updated
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Human-readable message
        - type: `string`
      - `status` *required*: `object (4 properties)`
        - description: Response for Blob service status
        - type: `object (4 properties)`
      - `success` *required*: `boolean`
        - description: Whether the operation succeeded
        - type: `boolean`
  - `401`: Unauthorized
  - `404`: Blob service not enabled
  - `500`: Internal server error

### `GET /blob/{project_id}/{path}`

- operationId: `blob_download`
- summary: Download a blob
- tags: `Blob`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
  - `Range` (header): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Blob content
  - `206`: The requested byte range of the blob, with the headers of a full read
  - `404`: Blob not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `416`: The range starts at or past the end of the blob
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `HEAD /blob/{project_id}/{path}`

- operationId: `blob_head`
- summary: Get blob metadata
- tags: `Blob`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Blob metadata in headers
  - `404`: Blob not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /consumer-deploys/templates`

- operationId: `list_consumer_deploy_templates`
- summary: List the curated consumer deploy template catalog.
- tags: `Consumer Deploy`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of deploy templates
    - `application/json`:
      - type: `object (1 properties)`
      - `templates` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /dns/lookup`

- operationId: `lookup_dns_a_records`
- summary: Lookup DNS A records for a domain
- tags: `DNS`
- parameters:
  - `domain` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved DNS A records
    - `application/json`:
      - type: `object (4 properties)`
      - `count` *required*: `integer`
        - description: Number of records found
        - type: `integer`
      - `dns_servers` *required*: `array<string>`
        - description: DNS servers used for the lookup
        - type: `array<string>`
      - `domain` *required*: `string`
        - description: Domain name that was queried
        - type: `string`
      - `records` *required*: `array<string>`
        - description: List of A record IP addresses
        - type: `array<string>`
  - `400`: Invalid domain name or lookup failed
    - `application/json`:
      - type: `object (2 properties)`
      - `domain` *required*: `string`
        - description: Domain name that failed
        - type: `string`
      - `error` *required*: `string`
        - description: Error message
        - type: `string`

### `POST /emails/validate`

- operationId: `validate_email`
- summary: Validate an email address
- tags: `Email Validation`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `email` *required*: `string`
      - description: Email address to validate
      - type: `string`
- responses:
  - `200`: Email validation result
    - `application/json`:
      - type: `object (6 properties)`
      - `email` *required*: `string`
        - description: The email address that was validated
        - type: `string`
      - `is_reachable` *required*: `string`
        - description: Email reachability status
        - type: `string`
      - `misc` *required*: `object (4 properties)`
        - description: Miscellaneous validation result
        - type: `object (4 properties)`
      - `mx` *required*: `object (3 properties)`
        - description: MX (Mail Exchange) validation result
        - type: `object (3 properties)`
      - `smtp` *required*: `object (6 properties)`
        - description: SMTP validation result
        - type: `object (6 properties)`
      - `syntax` *required*: `object (4 properties)`
        - description: Syntax validation result
        - type: `object (4 properties)`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `GET /emails/{email_id}/track/click/{link_index}`

- operationId: `track_click`
- summary: Track email link click - redirects to original URL
- description: This endpoint replaces original links in tracked emails.
No authentication required - it's called when the recipient clicks a link.
- tags: `Email Tracking`
- parameters:
  - `email_id` (path) *required*: `string`
  - `link_index` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to original URL
  - `404`: Link not found

### `GET /emails/{email_id}/track/open`

- operationId: `track_open`
- summary: Track email open - returns a 1x1 transparent GIF
- description: This endpoint is embedded as an <img> tag in emails.
No authentication required - it's called by the email client.
- tags: `Email Tracking`
- parameters:
  - `email_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: 1x1 transparent tracking pixel
  - `404`: Email not found

### `GET /geo/{ip}`

- operationId: `get_ip_geolocation`
- summary: Get geolocation information for an IP address
- tags: `geo`
- parameters:
  - `ip` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Geolocation information retrieved
    - `application/json`:
      - type: `object (9 properties)`
      - `city`: `['string', 'null']`
        - description: City name
        - type: `['string', 'null']`
      - `country`: `['string', 'null']`
        - description: Country name
        - type: `['string', 'null']`
      - `country_code`: `['string', 'null']`
        - description: ISO country code (2 letters)
        - type: `['string', 'null']`
      - `ip` *required*: `string`
        - description: IP address that was geolocated
        - type: `string`
      - `is_eu` *required*: `boolean`
        - description: Whether the IP is in the European Union
        - type: `boolean`
      - `latitude`: `['number', 'null']`
        - description: Latitude coordinate
        - type: `['number', 'null']`
      - `longitude`: `['number', 'null']`
        - description: Longitude coordinate
        - type: `['number', 'null']`
      - `region`: `['string', 'null']`
        - description: Region/state name
        - type: `['string', 'null']`
      - `timezone`: `['string', 'null']`
        - description: Timezone identifier
        - type: `['string', 'null']`
  - `400`: Invalid IP address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Authentication required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: IP address not found in database
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /git-providers/{provider_id}/callback`

- operationId: `handle_git_provider_oauth_callback`
- summary: Handle OAuth callback for a git provider
- tags: `Git Providers`
- parameters:
  - `provider_id` (path) *required*: `integer`
  - `code` (query) *required*: `string`
  - `state` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to success page
  - `400`: Bad request
  - `404`: Provider not found
  - `500`: Internal server error

### `GET /git/public/{provider}/{owner}/{repo}`

- operationId: `get_public_repository`
- summary: Get information about a public repository (supports GitHub and GitLab)
- tags: `Public Repositories`
- parameters:
  - `provider` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `repo` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Repository information
    - `application/json`:
      - type: `object (8 properties)`
      - `default_branch` *required*: `string`
        - description: Default branch name
        - type: `string`
      - `description`: `['string', 'null']`
        - description: Repository description
        - type: `['string', 'null']`
      - `forks` *required*: `integer`
        - description: Fork count
        - type: `integer`
      - `full_name` *required*: `string`
        - description: Full repository name (owner/repo)
        - type: `string`
      - `language`: `['string', 'null']`
        - description: Primary programming language
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - description: Repository name
        - type: `string`
      - `owner` *required*: `string`
        - description: Repository owner
        - type: `string`
      - `stars` *required*: `integer`
        - description: Star count
        - type: `integer`
  - `400`: Provider not supported
  - `404`: Repository not found
  - `429`: API rate limit exceeded
  - `500`: Internal server error

### `GET /git/public/{provider}/{owner}/{repo}/branches`

- operationId: `get_public_branches`
- summary: Get branches for a public repository (supports GitHub and GitLab)
- tags: `Public Repositories`
- parameters:
  - `provider` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `repo` (path) *required*: `string`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: List of branches
    - `application/json`:
      - type: `object (1 properties)`
      - `branches` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `400`: Provider not supported
  - `404`: Repository not found
  - `429`: API rate limit exceeded
  - `500`: Internal server error

### `GET /git/public/{provider}/{owner}/{repo}/presets`

- operationId: `detect_public_presets`
- summary: Detect presets for a public repository (supports GitHub and GitLab)
- tags: `Public Repositories`
- parameters:
  - `provider` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `repo` (path) *required*: `string`
  - `branch` (query): `['string', 'null']`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Detected presets
    - `application/json`:
      - type: `object (2 properties)`
      - `branch` *required*: `string`
        - description: Branch name where presets were detected
        - type: `string`
      - `presets` *required*: `array<object (7 properties)>`
        - description: List of detected presets
        - type: `array<object (7 properties)>`
  - `400`: Provider not supported
  - `404`: Repository or branch not found
  - `429`: API rate limit exceeded
  - `500`: Internal server error

### `POST /imports/discover`

- operationId: `discover_workloads`
- summary: Discover workloads from a source
- tags: `Imports`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `credentials`: `object (4 properties)`
      - description: Platform-specific credentials for accessing the source system.
      - type: `object (4 properties)`
    - `selector`: `object (5 properties)`
      - description: Selector for discovering workloads
      - type: `object (5 properties)`
    - `source` *required*: `string`
      - description: Import source identifier
      - type: `string`
- responses:
  - `200`: List of discovered workloads
    - `application/json`:
      - type: `object (1 properties)`
      - `workloads` *required*: `array<object (7 properties)>`
        - description: Discovered workloads
        - type: `array<object (7 properties)>`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `POST /imports/execute`

- operationId: `execute_import`
- summary: Execute an import
- tags: `Imports`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `directory` *required*: `string`
      - description: Project directory
      - type: `string`
    - `dry_run`: `['boolean', 'null']`
      - description: Dry run mode (don't create resources)
      - type: `['boolean', 'null']`
    - `main_branch` *required*: `string`
      - description: Main branch name
      - type: `string`
    - `preset` *required*: `string`
      - description: Preset to use for the project (e.g., "nextjs", "express", "docker")
      - type: `string`
    - `project_name` *required*: `string`
      - description: Project name to use (overrides the name from the plan)
      - type: `string`
    - `session_id` *required*: `string`
      - description: Session ID from plan creation
      - type: `string`
- responses:
  - `202`: Import execution started
    - `application/json`:
      - type: `object (6 properties)`
      - `deployment_id`: `['integer', 'null']`
        - description: Created deployment ID (if completed)
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - description: Created environment ID (if completed)
        - type: `['integer', 'null']`
      - `project_id`: `['integer', 'null']`
        - description: Created project ID (if completed)
        - type: `['integer', 'null']`
      - `session_id` *required*: `string`
        - description: Session ID
        - type: `string`
      - `status` *required*: `string`
        - description: Import execution status
        - type: `string`
      - `step_results` *required*: `array<object (7 properties)>`
        - description: Per-step results (in execution order)
        - type: `array<object (7 properties)>`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `POST /imports/plan`

- operationId: `create_plan`
- summary: Create an import plan
- tags: `Imports`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `credentials`: `object (4 properties)`
      - description: Platform-specific credentials for accessing the source system.
      - type: `object (4 properties)`
    - `repository_id`: `['integer', 'null']`
      - description: Optional repository ID to associate with the import
      - type: `['integer', 'null']`
    - `source` *required*: `string`
      - description: Import source identifier
      - type: `string`
    - `workload_id` *required*: `string`
      - description: Unique identifier for a workload in the source system
      - type: `string`
- responses:
  - `200`: Import plan created
    - `application/json`:
      - type: `object (4 properties)`
      - `can_execute` *required*: `boolean`
        - description: Whether the plan can be executed
        - type: `boolean`
      - `plan` *required*: `object (12 properties)`
        - description: Complete import plan describing all operations to onboard a workload.
        - type: `object (12 properties)`
      - `session_id` *required*: `string`
        - description: Session ID for tracking
        - type: `string`
      - `validation` *required*: `object (3 properties)`
        - description: Complete validation report
        - type: `object (3 properties)`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /imports/sources`

- operationId: `list_sources`
- summary: List available import sources
- tags: `Imports`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of available import sources
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /imports/{session_id}`

- operationId: `get_import_status`
- summary: Get import status
- tags: `Imports`
- parameters:
  - `session_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Import status
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - description: Created at timestamp
        - type: `string`
      - `deployment_id`: `['integer', 'null']`
        - description: Created deployment ID
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - description: Created environment ID
        - type: `['integer', 'null']`
      - `errors` *required*: `array<string>`
        - description: Errors (if any)
        - type: `array<string>`
      - `plan`: `object (12 properties) | null`
        - type: `object (12 properties) | null`
      - `project_id`: `['integer', 'null']`
        - description: Created project ID
        - type: `['integer', 'null']`
      - `session_id` *required*: `string`
        - description: Session ID
        - type: `string`
      - `status` *required*: `string`
        - description: Import execution status
        - type: `string`
      - `updated_at` *required*: `string`
        - description: Updated at timestamp
        - type: `string`
      - `validation`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `warnings` *required*: `array<string>`
        - description: Warnings (if any)
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Import session not found

### `GET /internal/nodes`

- operationId: `admin_list_nodes`
- summary: List all registered nodes (admin — session auth via `RequireAuth`)
- tags: `Nodes`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of nodes
    - `application/json`:
      - type: `object (2 properties)`
      - `nodes` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /internal/nodes/register`

- operationId: `register_node`
- summary: Register a new worker node or reconnect an existing one
- tags: `Nodes`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (14 properties)`
    - `address` *required*: `string`
      - description: Node's reachable address (e.g., "10.100.0.2" or "192.168.1.50")
      - type: `string`
    - `architecture`: `['string', 'null']`
      - description: Container platform of this node's Docker daemon (`linux/arm64`), read
      - type: `['string', 'null']`
    - `csr_pem`: `['string', 'null']`
      - description: Node-generated certificate signing request (PEM) for multi-node mTLS
      - type: `['string', 'null']`
    - `edge_public_key`: `['string', 'null']`
      - description: X25519 public key for ECIES certificate encryption (base64-encoded, edge nodes only)
      - type: `['string', 'null']`
    - `join_token`: `['string', 'null']`
      - description: Join token to authorize this registration (must match the token generated in Settings)
      - type: `['string', 'null']`
    - `labels`: `any`
      - description: Labels for scheduling (e.g., {"region": "us-east", "gpu": "true"})
      - type: `any`
    - `name` *required*: `string`
      - description: Unique name for this node
      - type: `string`
    - `prior_token`: `['string', 'null']`
      - description: The node's *current* token, supplied to prove possession when
      - type: `['string', 'null']`
    - `private_address` *required*: `string`
      - description: Private/WireGuard address for inter-node communication
      - type: `string`
    - `public_endpoint`: `['string', 'null']`
      - description: Public endpoint for `WireGuard` (e.g., "203.0.113.1:51820")
      - type: `['string', 'null']`
    - `request_mesh_address`: `['boolean', 'null']`
      - description: When true, the control plane assigns this node a worker-mesh
      - type: `['boolean', 'null']`
    - `role`: `['string', 'null']`
      - description: Node role (default: "worker")
      - type: `['string', 'null']`
    - `token` *required*: `string`
      - description: Registration token (plaintext, will be hashed before storage)
      - type: `string`
    - `wg_public_key`: `['string', 'null']`
      - description: `WireGuard` public key
      - type: `['string', 'null']`
- responses:
  - `200`: Node reconnected successfully
    - `application/json`:
      - type: `object (7 properties)`
      - `ca_cert_pem`: `['string', 'null']`
        - description: The cluster CA certificate (PEM) the node pins as its trust root.
        - type: `['string', 'null']`
      - `cert_pem`: `['string', 'null']`
        - description: The signed per-node leaf certificate (PEM) the agent serves as its TLS
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `wg_mesh_address`: `['string', 'null']`
        - description: The worker-mesh `WireGuard` address assigned to this node. Present
        - type: `['string', 'null']`
  - `201`: Node registered successfully
    - `application/json`:
      - type: `object (7 properties)`
      - `ca_cert_pem`: `['string', 'null']`
        - description: The cluster CA certificate (PEM) the node pins as its trust root.
        - type: `['string', 'null']`
      - `cert_pem`: `['string', 'null']`
        - description: The signed per-node leaf certificate (PEM) the agent serves as its TLS
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `wg_mesh_address`: `['string', 'null']`
        - description: The worker-mesh `WireGuard` address assigned to this node. Present
        - type: `['string', 'null']`
  - `400`: Validation error
  - `409`: The servers allowance of the license is used up
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}`

- operationId: `admin_get_node`
- summary: Get a specific node by ID (admin — session auth via `RequireAuth`)
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Node details
    - `application/json`:
      - type: `object (11 properties)`
      - `address` *required*: `string`
        - type: `string`
      - `architecture`: `['string', 'null']`
        - description: Container platform this node runs (`linux/amd64`, `linux/arm64`), or
        - type: `['string', 'null']`
      - `capacity` *required*: `any`
        - description: Resource capacity/usage metrics from the latest heartbeat
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `labels` *required*: `any`
        - type: `any`
      - `last_heartbeat`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `private_address` *required*: `string`
        - type: `string`
      - `role` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Node not found
  - `500`: Internal server error

### `DELETE /internal/nodes/{node_id}`

- operationId: `admin_remove_node`
- summary: Remove a node from the cluster entirely. The node should be drained first
to ensure containers have been rescheduled. If the node still has active
containers, it will be drained automatically before removal.
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Node removed
    - `application/json`:
      - type: `object (2 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Node not found
  - `409`: Node still has active containers
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}/containers`

- operationId: `admin_list_node_containers`
- summary: List all containers running on a specific node
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Containers on this node
    - `application/json`:
      - type: `object (2 properties)`
      - `containers` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Node not found
  - `500`: Internal server error

### `POST /internal/nodes/{node_id}/dns/ack`

- operationId: `post_dns_ack`
- summary: `POST /internal/nodes/{node_id}/dns/ack`
- tags: `Internal DNS`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `applied_generation` *required*: `integer`
      - description: Highest generation the agent has actually applied locally.
      - type: `integer`
- responses:
  - `200`: ACK accepted
    - `application/json`:
      - type: `object (3 properties)`
      - `applied_generation` *required*: `integer`
        - type: `integer`
      - `node_id` *required*: `integer`
        - type: `integer`
      - `server_generation` *required*: `integer`
        - type: `integer`
  - `400`: ACK higher than server generation
  - `401`: Missing or invalid bearer token
  - `404`: Node not found
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}/dns/changes`

- operationId: `get_dns_changes`
- summary: `GET /internal/nodes/{node_id}/dns/changes?since=N`
- tags: `Internal DNS`
- parameters:
  - `node_id` (path) *required*: `integer`
  - `since` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Diff or full snapshot
    - `application/json`:
      - type: `object (4 properties)`
      - `full_snapshot` *required*: `boolean`
        - description: `true` ⇒ replace the local zone with `records`. `false` ⇒ merge
        - type: `boolean`
      - `generation` *required*: `integer`
        - description: Highest generation included in this response. Agent ACKs this back.
        - type: `integer`
      - `records` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `removed_ids` *required*: `array<integer>`
        - description: IDs the agent should remove from its zone. Always empty in the v1
        - type: `array<integer>`
  - `401`: Missing or invalid bearer token
  - `404`: Node not found
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}/drain`

- operationId: `admin_drain_status`
- summary: Get the drain status for a node, including migration progress.
- description: Returns container counts and whether the drain is complete.
Can be polled to track drain progress.
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Drain status
    - `application/json`:
      - type: `object (7 properties)`
      - `can_remove` *required*: `boolean`
        - description: Can the node be safely removed?
        - type: `boolean`
      - `drain_complete` *required*: `boolean`
        - description: Whether the drain is complete (all containers migrated)
        - type: `boolean`
      - `message` *required*: `string`
        - type: `string`
      - `node_id` *required*: `integer`
        - type: `integer`
      - `node_name` *required*: `string`
        - type: `string`
      - `remaining_containers` *required*: `integer`
        - description: Number of containers still on this node
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Node not found
  - `500`: Internal server error

### `POST /internal/nodes/{node_id}/drain`

- operationId: `admin_drain_node`
- summary: Drain a node: mark it as "draining" so no new replicas are scheduled on it,
and trigger redeployment of all affected environments so their containers
are rescheduled to healthy nodes.
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Node drain initiated
    - `application/json`:
      - type: `object (5 properties)`
      - `affected_environments` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Node not found
  - `500`: Internal server error

### `DELETE /internal/nodes/{node_id}/drain`

- operationId: `admin_undrain_node`
- summary: Undrain (reactivate) a node so it can accept new deployments again.
Only works for nodes in "draining" or "drained" status.
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Node reactivated
    - `application/json`:
      - type: `object (4 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Node not in drainable state
  - `401`: Unauthorized
  - `404`: Node not found

### `POST /internal/nodes/{node_id}/heartbeat`

- operationId: `node_heartbeat`
- summary: Receive a heartbeat from a worker node
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `architecture`: `['string', 'null']`
      - description: Container platform reported by the agent (`linux/arm64`). Sent on every
      - type: `['string', 'null']`
    - `capacity`: `any`
      - description: Resource capacity/usage info as JSON (`cpu_usage`, `memory_usage`, etc.)
      - type: `any`
    - `containers`: `['array', 'null']`
      - description: Container inventory for reconciliation (sent on first heartbeat after agent startup).
      - type: `['array', 'null']`
    - `labels`: `any`
      - description: Updated node labels for scheduling (allows runtime label changes).
      - type: `any`
- responses:
  - `200`: Heartbeat received
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Node not found
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}/network/peers`

- operationId: `list_peers`
- summary: `GET /internal/nodes/{node_id}/network/peers`
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Peer list and self-allocation
    - `application/json`:
      - type: `object (6 properties)`
      - `alloc`: `object (4 properties) | null`
        - type: `object (4 properties) | null`
      - `cluster_dns_enabled` *required*: `boolean`
        - description: Whether the cluster-DNS resolver is enabled on this control plane
        - type: `boolean`
      - `overlay_members` *required*: `array<object (2 properties)>`
        - description: Every managed-service member's overlay address and organization; the
        - type: `array<object (2 properties)>`
      - `overlay_transport` *required*: `object (5 properties)`
        - description: Overlay transport the control plane wants every worker to run
        - type: `object (5 properties)`
      - `own_wg_address`: `['string', 'null']`
        - description: Caller's own worker-mesh WG address (its registered
        - type: `['string', 'null']`
      - `peers` *required*: `array<object (7 properties)>`
        - description: All other nodes with a `compute_cidr` set, excluding the caller.
        - type: `array<object (7 properties)>`
  - `401`: Missing or invalid bearer token
  - `404`: Node not found
  - `500`: Internal server error

### `GET /internal/nodes/{node_id}/s3-credentials/{s3_source_id}`

- operationId: `get_s3_credentials`
- summary: Get decrypted S3 credentials for a backup/restore operation.
- description: Agents call this endpoint to receive the S3 credentials they need to upload
or download backups. The credentials are decrypted from the stored S3 source
and returned over the authenticated TLS/WireGuard channel.
- tags: `Nodes`
- parameters:
  - `node_id` (path) *required*: `integer`
  - `s3_source_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: S3 credentials
    - `application/json`:
      - type: `object (6 properties)`
      - `access_key_id` *required*: `string`
        - type: `string`
      - `bucket_name` *required*: `string`
        - type: `string`
      - `endpoint`: `['string', 'null']`
        - type: `['string', 'null']`
      - `force_path_style` *required*: `boolean`
        - type: `boolean`
      - `region` *required*: `string`
        - type: `string`
      - `secret_key` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: S3 source not found
  - `500`: Internal server error

### `GET /ip-access-control`

- operationId: `list_ip_access_control`
- summary: List all IP access control rules
- tags: `IP Access Control`
- parameters:
  - `action` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of IP access control rules
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /ip-access-control`

- operationId: `create_ip_access_control`
- summary: Create a new IP access control rule
- tags: `IP Access Control`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `action` *required*: `string`
      - description: Action to take: "block" or "allow"
      - type: `string`
    - `ip_address` *required*: `string`
      - description: IP address in CIDR notation (e.g., "192.168.1.1" or "10.0.0.0/24")
      - type: `string`
    - `reason`: `['string', 'null']`
      - description: Optional reason for the action
      - type: `['string', 'null']`
- responses:
  - `201`: IP access control rule created
    - `application/json`:
      - type: `object (7 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_address` *required*: `string`
        - type: `string`
      - `reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Duplicate IP address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /ip-access-control/check/{ip}`

- operationId: `check_ip_blocked`
- summary: Check if an IP address is blocked
- tags: `IP Access Control`
- parameters:
  - `ip` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: IP block status
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /ip-access-control/{id}`

- operationId: `get_ip_access_control`
- summary: Get a single IP access control rule by ID
- tags: `IP Access Control`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: IP access control rule details
    - `application/json`:
      - type: `object (7 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_address` *required*: `string`
        - type: `string`
      - `reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: IP access control rule not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /ip-access-control/{id}`

- operationId: `update_ip_access_control`
- summary: Update an IP access control rule
- tags: `IP Access Control`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `action`: `['string', 'null']`
      - description: Optional new action
      - type: `['string', 'null']`
    - `ip_address`: `['string', 'null']`
      - description: Optional new IP address
      - type: `['string', 'null']`
    - `reason`: `['string', 'null']`
      - description: Optional new reason
      - type: `['string', 'null']`
- responses:
  - `200`: IP access control rule updated
    - `application/json`:
      - type: `object (7 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_address` *required*: `string`
        - type: `string`
      - `reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: IP access control rule not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /ip-access-control/{id}`

- operationId: `delete_ip_access_control`
- summary: Delete an IP access control rule
- tags: `IP Access Control`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: IP access control rule deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: IP access control rule not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /lb/routes`

- operationId: `list_routes`
- tags: `Load Balancer`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of routes
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `500`: Internal server error

### `POST /lb/routes`

- operationId: `create_route`
- tags: `Load Balancer`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `domain` *required*: `string`
      - type: `string`
    - `host` *required*: `string`
      - type: `string`
    - `port` *required*: `integer`
      - type: `integer`
    - `route_type`: `['string', 'null']`
      - description: Route type: "http" (default) matches on HTTP Host header,
      - type: `['string', 'null']`
- responses:
  - `201`: Route created successfully
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `host` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `port` *required*: `integer`
        - type: `integer`
      - `route_type` *required*: `string`
        - description: Route type: "http" or "tls"
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid request

### `GET /lb/routes/{domain}`

- operationId: `get_route`
- tags: `Load Balancer`
- parameters:
  - `domain` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Route found
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `host` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `port` *required*: `integer`
        - type: `integer`
      - `route_type` *required*: `string`
        - description: Route type: "http" or "tls"
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `404`: Route not found

### `PUT /lb/routes/{domain}`

- operationId: `update_route`
- tags: `Load Balancer`
- parameters:
  - `domain` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `enabled` *required*: `boolean`
      - type: `boolean`
    - `host` *required*: `string`
      - type: `string`
    - `port` *required*: `integer`
      - type: `integer`
    - `route_type`: `['string', 'null']`
      - description: Route type: "http" (default) matches on HTTP Host header,
      - type: `['string', 'null']`
- responses:
  - `200`: Route updated successfully
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `host` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `port` *required*: `integer`
        - type: `integer`
      - `route_type` *required*: `string`
        - description: Route type: "http" or "tls"
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `404`: Route not found

### `DELETE /lb/routes/{domain}`

- operationId: `delete_route`
- tags: `Load Balancer`
- parameters:
  - `domain` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Route deleted successfully
  - `404`: Route not found

### `DELETE /licenses`

- operationId: `uninstall_license`
- summary: Uninstall the active license, restoring the bound org to Community. The
record is superseded (kept as history), never deleted. Super-admin only;
audited by fingerprint.
- tags: `Licensing`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: License uninstalled; Community restored
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Human-readable outcome.
        - type: `string`
      - `previous` *required*: `object (11 properties)`
        - description: The safe, non-secret view of an installed license record.
        - type: `object (11 properties)`
      - `restored_plan_key` *required*: `string`
        - description: The plan the bound org was restored to (Community default).
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No active license to uninstall
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /licenses/history`

- operationId: `license_history`
- summary: Paginated install history, newest first. Never returns raw keys. Super-admin
only.
- tags: `Licensing`
- parameters:
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: License install history (no raw keys)
    - `application/json`:
      - type: `object (4 properties)`
      - `items` *required*: `array<object (11 properties)>`
        - description: License records, newest first. None contain the raw key.
        - type: `array<object (11 properties)>`
      - `page` *required*: `integer`
        - description: The page returned.
        - type: `integer`
      - `page_size` *required*: `integer`
        - description: The page size used.
        - type: `integer`
      - `total` *required*: `integer`
        - description: Total number of records across all pages.
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /licenses/install`

- operationId: `install_license`
- summary: Install a license key: verify offline, materialize its plan, and record the
install. Super-admin only; audited by fingerprint.
- tags: `Licensing`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `key` *required*: `string`
      - description: The compact Ed25519-signed license JWT to install. Never echoed back in
      - type: `string`
- responses:
  - `200`: License installed; decoded claims echoed (never the raw key)
    - `application/json`:
      - type: `object (11 properties)`
      - `allowances` *required*: `object (6 properties)`
        - description: The non-secret allowances projection surfaced to clients.
        - type: `object (6 properties)`
      - `expires_at` *required*: `string`
        - description: When the key expires (`exp`).
        - type: `string`
      - `features` *required*: `array<string>`
        - description: Feature flags granted by the key.
        - type: `array<string>`
      - `fingerprint` *required*: `string`
        - description: SHA-256 fingerprint of the raw key (safe to display and correlate on).
        - type: `string`
      - `installed_at` *required*: `string`
        - description: When this record was installed on this installation.
        - type: `string`
      - `issued_at` *required*: `string`
        - description: When the key was issued (`iat`).
        - type: `string`
      - `org_binding` *required*: `string`
        - description: Organization slug the key is bound to (the JWT `sub`).
        - type: `string`
      - `plan` *required*: `string`
        - description: Human-readable plan name decoded from the key's claims.
        - type: `string`
      - `plan_key` *required*: `string`
        - description: The plan key materialized into the entitlement rows.
        - type: `string`
      - `sku`: `['string', 'null']`
        - description: SKU marker, if the key carried one.
        - type: `['string', 'null']`
      - `superseded_at`: `['string', 'null']`
        - description: Set once the record has been superseded or uninstalled; `null` while
        - type: `['string', 'null']`
  - `400`: Invalid, expired, or tampered key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Bound organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /licenses/status`

- operationId: `license_status`
- summary: Current license status: the active plan/expiry/features, or Community mode.
Never returns the raw key. The `SystemAdmin` view also carries the evaluated
licensing state (`state`) that the admin dashboard's persistent banner
reads (loop 05 Phase 5, box192).
- description: Two audiences, two access paths (docs/explanation/license-keys.md —
"HTTP API and UI"):
- `SystemAdmins` get the full platform-wide view, unchanged from loop 3/5.
- Org owners get the same non-secret projection, but only when their
  verified credential is bound to an organization they own. A caller with
  no org-bound credential or no owner-level access fails closed as `403`;
  an owner of a different organization than the one the active license is
  bound to fails closed as `404` rather than confirming a foreign license
  exists.
- tags: `Licensing`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Current licensing state (no raw key)
    - `application/json`:
      - type: `object (4 properties)`
      - `community_mode` *required*: `boolean`
        - description: `true` when the installation runs on the Community default (no license).
        - type: `boolean`
      - `installed` *required*: `boolean`
        - description: `true` when an active license is installed, `false` in Community mode.
        - type: `boolean`
      - `license`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `state`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions (not SystemAdmin and not an Owner of the requested org)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Org-owner request whose org does not own the active license
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /logout`

- operationId: `logout`
- summary: Logs the user out of **this** session (Decision D8, review F-6-30):
the session the request authenticated with is revoked — the user's other
devices stay signed in. Ending every session is the explicit
`POST /auth/logout/all` action. The session id comes from the verified
auth context (the request's own credential), never from caller input.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully logged out
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /metering/health`

- operationId: `meteringHealth`
- tags: `Metering`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Metering service is healthy

### `GET /notification-events`

- operationId: `list_notification_events`
- summary: The event catalogue: what can be templated, what it is switched by, and
which variables each event's templates may use.
- tags: `Notification Templates`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The event catalogue
    - `application/json`:
      - type: `object (3 properties)`
      - `categories` *required*: `array<object (4 properties)>`
        - description: Categories, in display order.
        - type: `array<object (4 properties)>`
      - `events` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `short_text_max_chars` *required*: `integer`
        - description: The rendered-length ceiling for `short_text`.
        - type: `integer`
  - `401`: Unauthorized

### `GET /notification-outbox`

- operationId: `list_notification_outbox`
- summary: Recent messages in the delivery log.
- tags: `Notification Delivery Log`
- parameters:
  - `status` (query): `['string', 'null']`
  - `channel` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Recent notification messages
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /notification-outbox/{id}/retry`

- operationId: `retry_notification_message`
- summary: Put a failed or dead-lettered message back in the queue.
- tags: `Notification Delivery Log`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The message is queued again
    - `application/json`:
      - type: `object (2 properties)`
      - `attempts` *required*: `array<object (9 properties)>`
        - description: The attempts recorded so far, newest last.
        - type: `array<object (9 properties)>`
      - `message` *required*: `object (16 properties)`
        - description: One message in the delivery log.
        - type: `object (16 properties)`
  - `401`: Unauthorized
  - `404`: Message not found
  - `409`: The message is not in a retryable state
  - `500`: Internal server error

### `GET /notification-preferences`

- operationId: `get_preferences`
- summary: Get notification preferences
- tags: `Notification Preferences`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved preferences
    - `application/json`:
      - type: `object (23 properties)`
      - `backup_failures_enabled` *required*: `boolean`
        - type: `boolean`
      - `backup_successes_enabled` *required*: `boolean`
        - type: `boolean`
      - `batch_similar_notifications` *required*: `boolean`
        - type: `boolean`
      - `build_errors_enabled` *required*: `boolean`
        - type: `boolean`
      - `deployment_failures_enabled` *required*: `boolean`
        - type: `boolean`
      - `digest_sections` *required*: `object (5 properties)`
        - description: Sections that can be included in the weekly digest
        - type: `object (5 properties)`
      - `digest_send_day` *required*: `string`
        - type: `string`
      - `digest_send_time` *required*: `string`
        - type: `string`
      - `dns_changes_enabled` *required*: `boolean`
        - type: `boolean`
      - `domain_expiration_enabled` *required*: `boolean`
        - type: `boolean`
      - `email_enabled` *required*: `boolean`
        - type: `boolean`
      - `error_threshold` *required*: `integer`
        - type: `integer`
      - `error_time_window` *required*: `integer`
        - type: `integer`
      - `load_balancer_issues_enabled` *required*: `boolean`
        - type: `boolean`
      - `minimum_severity` *required*: `string`
        - type: `string`
      - `retention_policy_violations_enabled` *required*: `boolean`
        - type: `boolean`
      - `route_downtime_enabled` *required*: `boolean`
        - type: `boolean`
      - `runtime_errors_enabled` *required*: `boolean`
        - type: `boolean`
      - `s3_connection_issues_enabled` *required*: `boolean`
        - type: `boolean`
      - `slack_enabled` *required*: `boolean`
        - type: `boolean`
      - `ssl_days_before_expiration` *required*: `integer`
        - type: `integer`
      - `ssl_expiration_enabled` *required*: `boolean`
        - type: `boolean`
      - `weekly_digest_enabled` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `500`: Internal server error

### `PUT /notification-preferences`

- operationId: `update_preferences`
- summary: Update notification preferences
- tags: `Notification Preferences`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `preferences` *required*: `object (23 properties)`
      - type: `object (23 properties)`
- responses:
  - `200`: Successfully updated preferences
    - `application/json`:
      - type: `object (23 properties)`
      - `backup_failures_enabled` *required*: `boolean`
        - type: `boolean`
      - `backup_successes_enabled` *required*: `boolean`
        - type: `boolean`
      - `batch_similar_notifications` *required*: `boolean`
        - type: `boolean`
      - `build_errors_enabled` *required*: `boolean`
        - type: `boolean`
      - `deployment_failures_enabled` *required*: `boolean`
        - type: `boolean`
      - `digest_sections` *required*: `object (5 properties)`
        - description: Sections that can be included in the weekly digest
        - type: `object (5 properties)`
      - `digest_send_day` *required*: `string`
        - type: `string`
      - `digest_send_time` *required*: `string`
        - type: `string`
      - `dns_changes_enabled` *required*: `boolean`
        - type: `boolean`
      - `domain_expiration_enabled` *required*: `boolean`
        - type: `boolean`
      - `email_enabled` *required*: `boolean`
        - type: `boolean`
      - `error_threshold` *required*: `integer`
        - type: `integer`
      - `error_time_window` *required*: `integer`
        - type: `integer`
      - `load_balancer_issues_enabled` *required*: `boolean`
        - type: `boolean`
      - `minimum_severity` *required*: `string`
        - type: `string`
      - `retention_policy_violations_enabled` *required*: `boolean`
        - type: `boolean`
      - `route_downtime_enabled` *required*: `boolean`
        - type: `boolean`
      - `runtime_errors_enabled` *required*: `boolean`
        - type: `boolean`
      - `s3_connection_issues_enabled` *required*: `boolean`
        - type: `boolean`
      - `slack_enabled` *required*: `boolean`
        - type: `boolean`
      - `ssl_days_before_expiration` *required*: `integer`
        - type: `integer`
      - `ssl_expiration_enabled` *required*: `boolean`
        - type: `boolean`
      - `weekly_digest_enabled` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `500`: Internal server error

### `DELETE /notification-preferences`

- operationId: `delete_preferences`
- summary: Delete notification preferences
- tags: `Notification Preferences`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `204`: Successfully deleted preferences
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /notification-preferences/matrix`

- operationId: `get_preference_matrix`
- summary: The resolved category × channel grid for the caller, their organization
or the platform.
- tags: `Notification Preferences`
- parameters:
  - `scope` (query): `string | null`
- requestBody: _(none)_
- responses:
  - `200`: The resolved preference matrix
    - `application/json`:
      - type: `object (2 properties)`
      - `scope` *required*: `string`
        - description: Which layer a matrix request reads or writes.
        - type: `string`
      - `switches` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Platform layer needs a platform administrator
  - `500`: Internal server error

### `PUT /notification-preferences/matrix`

- operationId: `update_preference_matrix`
- summary: Set or clear switches at one layer.
- description: A mandatory category on email is refused with `400` rather than silently
ignored, so a client that thinks it turned security mail off learns that
it did not.
- tags: `Notification Preferences`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `scope`: `string | null`
      - type: `string | null`
    - `switches` *required*: `array<object (3 properties)>`
      - type: `array<object (3 properties)>`
- responses:
  - `200`: The matrix after the change
    - `application/json`:
      - type: `object (2 properties)`
      - `scope` *required*: `string`
        - description: Which layer a matrix request reads or writes.
        - type: `string`
      - `switches` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `400`: A switch that cannot be changed
  - `401`: Unauthorized
  - `403`: Layer needs an administrator
  - `500`: Internal server error

### `GET /notification-templates`

- operationId: `list_notification_templates`
- summary: List the stored template overrides visible to the caller: this
organization's and the platform's.
- tags: `Notification Templates`
- parameters:
  - `event` (query): `['string', 'null']`
  - `channel` (query): `['string', 'null']`
  - `locale` (query): `['string', 'null']`
  - `owner` (query): `string | null`
- requestBody: _(none)_
- responses:
  - `200`: Stored template overrides
    - `application/json`:
      - type: `array<object (14 properties)>`
  - `400`: Unknown event or channel
  - `401`: Unauthorized
  - `500`: Internal server error

### `PUT /notification-templates`

- operationId: `upsert_notification_template`
- summary: Create or replace one template override.
- description: The draft is rendered against the event's sample payload before it is
stored; a template that names an undeclared variable is rejected here,
never at send time.
- tags: `Notification Templates`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `body_html`: `['string', 'null']`
      - type: `['string', 'null']`
    - `body_text` *required*: `string`
      - type: `string`
    - `channel` *required*: `string`
      - type: `string`
    - `event` *required*: `string`
      - type: `string`
    - `locale`: `['string', 'null']`
      - description: Defaults to `en`.
      - type: `['string', 'null']`
    - `owner`: `string | null`
      - type: `string | null`
    - `short_text`: `['string', 'null']`
      - type: `['string', 'null']`
    - `subject`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Stored
    - `application/json`:
      - type: `object (14 properties)`
      - `bodies_visible` *required*: `boolean`
        - description: `false` when the bodies above were withheld: this is a platform row
        - type: `boolean`
      - `body_html`: `['string', 'null']`
        - type: `['string', 'null']`
      - `body_text` *required*: `string`
        - type: `string`
      - `channel` *required*: `string`
        - type: `string`
      - `event` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `locale` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for the platform layer.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `short_text`: `['string', 'null']`
        - type: `['string', 'null']`
      - `subject`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `updated_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `version` *required*: `integer`
        - type: `integer`
  - `400`: Unknown event/channel, or the template does not render
  - `401`: Unauthorized
  - `403`: Platform layer needs a platform administrator
  - `500`: Internal server error

### `DELETE /notification-templates`

- operationId: `delete_notification_template`
- summary: Delete one override — revert to whatever it inherits.
- tags: `Notification Templates`
- parameters:
  - `event` (query): `['string', 'null']`
  - `channel` (query): `['string', 'null']`
  - `locale` (query): `['string', 'null']`
  - `owner` (query): `string | null`
- requestBody: _(none)_
- responses:
  - `204`: Reverted to the inherited template
  - `400`: Unknown event or channel
  - `401`: Unauthorized
  - `403`: Platform layer needs a platform administrator
  - `404`: Nothing was overridden
  - `500`: Internal server error

### `POST /notification-templates/preview`

- operationId: `preview_notification_template`
- summary: Render a draft (or the current resolved template) with a sample payload.
- description: Always `200`: a template that does not render is a *result*, not an error
— the editor shows the issues under the fields they belong to.

# Why this needs write permission

The body carries template source, and the handler runs it. That is
interpreter execution on a request thread, not a read: the caller chooses
the program. It is gated on `NotificationProvidersWrite` — the same
permission that lets someone *store* a template — so the set of people who
can make the server evaluate a template is the set who could already do it
by saving one. Fuel, source caps and the blocking-pool timeout in
`crate::templates` bound what that execution can cost; this bounds who can
ask for it.
- tags: `Notification Templates`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `body_html`: `['string', 'null']`
      - type: `['string', 'null']`
    - `body_text`: `['string', 'null']`
      - type: `['string', 'null']`
    - `channel` *required*: `string`
      - type: `string`
    - `event` *required*: `string`
      - type: `string`
    - `locale`: `['string', 'null']`
      - type: `['string', 'null']`
    - `owner`: `string | null`
      - type: `string | null`
    - `payload`: `any`
      - description: Values to render with; missing keys fall back to the event's
      - type: `any`
    - `short_text`: `['string', 'null']`
      - type: `['string', 'null']`
    - `subject`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Rendered preview, or the reasons it did not render
    - `application/json`:
      - type: `object (7 properties)`
      - `html`: `['string', 'null']`
        - type: `['string', 'null']`
      - `issues` *required*: `array<object (2 properties)>`
        - description: One entry per field that failed, empty when `valid`.
        - type: `array<object (2 properties)>`
      - `payload` *required*: `any`
        - description: The payload the preview was rendered with, so the editor can show
        - type: `any`
      - `short_text`: `['string', 'null']`
        - type: `['string', 'null']`
      - `subject`: `['string', 'null']`
        - type: `['string', 'null']`
      - `text`: `['string', 'null']`
        - type: `['string', 'null']`
      - `valid` *required*: `boolean`
        - description: `true` when every field rendered.
        - type: `boolean`
  - `400`: Unknown event or channel
  - `401`: Unauthorized
  - `403`: Rendering a template needs write permission on notification providers; the platform layer needs a platform administrator
  - `500`: Internal server error

### `GET /notification-templates/resolved`

- operationId: `resolve_notification_template`
- summary: What one key resolves to today, and whether the requested layer set it.
- description: This is what the editor loads: an empty override still comes back with
the inherited bodies, so "start from what is being sent" is one click.
- tags: `Notification Templates`
- parameters:
  - `event` (query): `['string', 'null']`
  - `channel` (query): `['string', 'null']`
  - `locale` (query): `['string', 'null']`
  - `owner` (query): `string | null`
- requestBody: _(none)_
- responses:
  - `200`: The effective template
    - `application/json`:
      - type: `object (9 properties)`
      - `body_html`: `['string', 'null']`
        - type: `['string', 'null']`
      - `body_text` *required*: `string`
        - type: `string`
      - `channel` *required*: `string`
        - type: `string`
      - `event` *required*: `string`
        - type: `string`
      - `locale` *required*: `string`
        - description: The locale that supplied the body (may be the `en` fallback).
        - type: `string`
      - `origin` *required*: `string`
        - description: Where the winning template came from — the "inherited / overridden" badge
        - type: `string`
      - `overridden` *required*: `boolean`
        - description: `true` when the requested owner has a row of its own for this key —
        - type: `boolean`
      - `short_text`: `['string', 'null']`
        - type: `['string', 'null']`
      - `subject`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Unknown event or channel
  - `401`: Unauthorized
  - `403`: Platform layer needs a platform administrator
  - `500`: Internal server error

### `POST /onboarding/links/redeem`

- operationId: `redeem_onboarding_link`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `email` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `organization_name` *required*: `string`
      - type: `string`
    - `organization_slug` *required*: `string`
      - type: `string`
    - `password` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - type: `string`
    - `workspace_name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `user_id` *required*: `integer`
        - type: `integer`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The Community edition user or organization cap is reached (no license installed)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /onboarding/links/suggestions`

- operationId: `get_onboarding_suggestions`
- tags: `Organizations`
- parameters:
  - `token` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `intended_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `suggested_org_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `suggested_workspace_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /onboarding/policy`

- operationId: `public_onboarding_policy`
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `organization_policy` *required*: `string`
        - description: Minimal install policy safe to publish without tenant counts or names.
        - type: `string`
      - `registration` *required*: `string`
        - type: `string`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /onboarding/register`

- operationId: `onboarding_register`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `email` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `organization_name` *required*: `string`
      - type: `string`
    - `organization_slug` *required*: `string`
      - type: `string`
    - `password` *required*: `string`
      - type: `string`
    - `workspace_name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `user_id` *required*: `integer`
        - type: `integer`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /organizations`

- operationId: `list_organizations`
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /organizations`

- operationId: `create_organization`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
    - `workspace_name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /organizations/accept-invite`

- operationId: `accept_invite`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `token` *required*: `string`
      - description: The raw invite token from the acceptance URL (`?token=…`). Named
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `email_verified`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_sso`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `mfa_enabled`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_id` *required*: `integer`
        - type: `integer`
      - `user_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /organizations/invite-preview`

- operationId: `preview_invite`
- tags: `Organizations`
- parameters:
  - `token` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (4 properties)`
      - `email` *required*: `string`
        - type: `string`
      - `expires_at` *required*: `string`
        - type: `string`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_name` *required*: `string`
        - type: `string`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Too Many Requests
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /organizations/register-and-accept-invite`

- operationId: `register_and_accept_invite`
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `name` *required*: `string`
      - type: `string`
    - `password` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - description: The raw invite token from the acceptance URL (`?token=…`). Named
      - type: `string`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (5 properties)`
      - `email` *required*: `string`
        - type: `string`
      - `member_id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `user_id` *required*: `integer`
        - type: `integer`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The Community edition user cap is reached (no license installed)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/genai/traces`

- operationId: `query_genai_traces`
- summary: Query `GenAI` trace summaries — traces containing spans with `gen_ai.*` attributes.
- description: `duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`
span attributes (e.g. time-to-first-token, token latency) often follow the
`OTel` `GenAI` semantic conventions, which use **seconds** (a fractional
double), not milliseconds — do not read them as ms without converting.
- tags: `GenAI`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `service_name` (query): `string`
  - `gen_ai_system` (query): `string`
  - `gen_ai_model` (query): `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: GenAI trace summaries
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/genai/traces/{project_id}/{trace_id}`

- operationId: `get_genai_trace`
- summary: Get `GenAI` span details for a specific trace.
- description: `duration_ms` is the only field guaranteed to be milliseconds. `gen_ai.*`
span attributes (e.g. time-to-first-token, token latency) often follow the
`OTel` `GenAI` semantic conventions, which use **seconds** (a fractional
double), not milliseconds — do not read them as ms without converting.
- tags: `GenAI`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `trace_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: GenAI trace span details
    - `application/json`:
      - type: `object (5 properties)`
      - `event_count` *required*: `integer`
        - type: `integer`
      - `events` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `span_count` *required*: `integer`
        - type: `integer`
      - `spans` *required*: `array<object (58 properties)>`
        - type: `array<object (58 properties)>`
      - `trace_id` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/global/traces/{trace_id}`

- operationId: `getUnifiedTrace`
- summary: Assemble a unified cross-project span waterfall (Phase 2).
- description: Fans out to every project that holds spans for `trace_id` (up to 20
projects, 10,000 total spans).  Spans are annotated with
`project_id`/`project_name` and sorted by `start_time ASC`.
`truncated: true` signals a hit on either cap; `truncated_projects`
lists the dropped project IDs.  See ADR-027 §4 for the full design.
- tags: `Traces`
- parameters:
  - `trace_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Unified cross-project trace waterfall
    - `application/json`:
      - type: `object (11 properties)`
      - `end_time` *required*: `string`
        - type: `string`
      - `error_count` *required*: `integer`
        - type: `integer`
      - `has_redacted_spans` *required*: `boolean`
        - description: `true` when at least one project has `cross_project_trace_sharing = false`
        - type: `boolean`
      - `projects` *required*: `array<object (3 properties)>`
        - description: Projects that contributed spans to this result set.
        - type: `array<object (3 properties)>`
      - `span_count` *required*: `integer`
        - type: `integer`
      - `spans` *required*: `array<object (3 properties)>`
        - description: Annotated, merged span list sorted by `start_time ASC`.
        - type: `array<object (3 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
      - `total_duration_ms` *required*: `number`
        - description: Trace wall-clock duration in milliseconds (`end_time – start_time`).
        - type: `number`
      - `trace_id` *required*: `string`
        - type: `string`
      - `truncated` *required*: `boolean`
        - description: `true` when the 20-project or 10,000-span cap was hit.
        - type: `boolean`
      - `truncated_projects` *required*: `array<integer>`
        - description: `project_ids` excluded due to truncation (most-recent `first_seen` dropped first).
        - type: `array<integer>`
  - `400`: trace_id is not 32 lowercase hex characters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions or deployment token
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/health/{project_id}`

- operationId: `get_health`
- summary: Get health summaries for a project.
- tags: `OTel`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Health summaries
    - `application/json`:
      - type: `object (1 properties)`
      - `summaries` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/insights/{project_id}`

- operationId: `list_insights`
- summary: List anomaly insights for a project.
- tags: `Insights`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `status` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Insights list
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/logs`

- operationId: `query_logs`
- summary: Query log records with optional filters.
- tags: `Telemetry Logs`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `severity` (query): `string`
  - `service_name` (query): `string`
  - `search` (query): `string`
  - `trace_id` (query): `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Log records
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/metric-label-keys`

- operationId: `list_metric_label_keys`
- summary: List the attribute (label) keys observed on a metric — powers the
label-filter key autocomplete.
- tags: `Telemetry Metrics`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `metric_name` (query) *required*: `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Distinct label keys
    - `application/json`:
      - type: `object (1 properties)`
      - `keys` *required*: `array<string>`
        - type: `array<string>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/metric-label-values`

- operationId: `list_metric_label_values`
- summary: List the distinct values seen for a label key on a metric — powers value
autocomplete once a key is chosen.
- tags: `Telemetry Metrics`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `metric_name` (query) *required*: `string`
  - `label_key` (query) *required*: `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Distinct label values
    - `application/json`:
      - type: `object (1 properties)`
      - `values` *required*: `array<string>`
        - type: `array<string>`
  - `400`: Invalid label key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/metric-names/{project_id}`

- operationId: `list_metric_names`
- summary: List distinct metric names for a project.
- tags: `Telemetry Metrics`
- parameters:
  - `project_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of metric names
    - `application/json`:
      - type: `object (1 properties)`
      - `names` *required*: `array<string>`
        - type: `array<string>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/metrics`

- operationId: `query_metrics`
- summary: Query metrics with time bucketing.
- tags: `Telemetry Metrics`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `metric_name` (query): `string`
  - `service_name` (query): `string`
  - `environment` (query): `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `bucket_interval` (query): `string`
  - `limit` (query): `integer`
  - `metric_type` (query): `string`
  - `aggregation` (query): `string`
  - `label_filters` (query): `string`
  - `group_by` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Metrics data
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
  - `400`: Invalid label key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/pipeline-stats`

- operationId: `get_pipeline_stats`
- summary: Get `OTel` pipeline statistics (admin/system view).
- tags: `OTel`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Pipeline statistics
    - `application/json`:
      - type: `object (1 properties)`
      - `stats` *required*: `object (11 properties)`
        - description: Internal pipeline statistics for self-observability.
        - type: `object (11 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/quota/{project_id}`

- operationId: `get_quota`
- summary: Get storage quota for a project.
- tags: `OTel`
- parameters:
  - `project_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Storage quota
    - `application/json`:
      - type: `object (1 properties)`
      - `quota` *required*: `object (7 properties)`
        - description: Quota usage information for a project.
        - type: `object (7 properties)`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/trace-summaries`

- operationId: `query_trace_summaries`
- summary: Query trace summaries — one row per trace with span count, error count,
root span info, and proper trace-level pagination.
- tags: `Traces`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `trace_id` (query): `string`
  - `service_name` (query): `string`
  - `status` (query): `string`
  - `min_duration_ms` (query): `number`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `name_pattern` (query): `string`
  - `attributes` (query): `string`
  - `sort_by` (query): `string`
  - `sort_order` (query): `string`
  - `include_total` (query): `boolean`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Trace summaries
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `total`: `['integer', 'null']`
        - description: Total traces matching the filters, ignoring pagination. Omitted when
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/traces`

- operationId: `query_traces`
- summary: Query trace spans with optional filters.
- description: Each returned span has a `duration_ms` field (float, milliseconds) — this is
the ONLY field guaranteed to be in milliseconds. Spans also carry an
`attributes` map of raw key/value pairs exactly as reported by the
instrumenting library: numeric attribute values may be seconds, milliseconds,
microseconds, or nanoseconds depending on that library's convention, and
nothing in this response labels the unit. Never assume an attribute's
numeric value shares `duration_ms`'s unit, and never state a duration in
milliseconds unless it came from a `duration_ms` field.
- tags: `Traces`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `trace_id` (query): `string`
  - `service_name` (query): `string`
  - `status` (query): `string`
  - `min_duration_ms` (query): `number`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `attributes` (query): `string`
  - `name_pattern` (query): `string`
  - `sort_by` (query): `string`
  - `sort_order` (query): `string`
  - `include_total` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Trace spans
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/traces/cross-project/{trace_id}`

- operationId: `getCrossProjectTraceSiblings`
- summary: Discover sibling projects that share the same `trace_id` (Phase 1 banner).
- description: Returns an empty `siblings` list when the trace is single-project — never
404. Project names are included so the UI can render navigation links
without a second round-trip.  See ADR-027 §3 for the full auth model and
topology-disclosure trade-offs.
- tags: `Traces`
- parameters:
  - `trace_id` (path) *required*: `string`
  - `exclude_project_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Sibling projects sharing this trace
    - `application/json`:
      - type: `object (2 properties)`
      - `siblings` *required*: `array<object (4 properties)>`
        - description: Projects other than the caller's that hold spans for this trace,
        - type: `array<object (4 properties)>`
      - `trace_id` *required*: `string`
        - description: The `trace_id` that was queried (echoed back for client convenience).
        - type: `string`
  - `400`: trace_id is not 32 lowercase hex characters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions or deployment token
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /otel/traces/{project_id}/{trace_id}`

- operationId: `get_trace`
- summary: Get all spans for a specific trace.
- description: Each span has a `duration_ms` field (float, milliseconds) — the ONLY field
guaranteed to be in milliseconds — plus an `attributes` map of raw
key/value pairs exactly as the instrumenting library reported them.
Numeric attribute values (e.g. connection-pool wait times, queue delays)
may be in seconds, milliseconds, microseconds, or nanoseconds depending on
that library's own convention; this response never labels the unit. When
explaining what a span spent time on, only quote milliseconds from
`duration_ms` (or from `start_time`/`end_time` deltas) — never assume a raw
attribute number is already in milliseconds.
- tags: `Traces`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `trace_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Trace spans tree
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/logs`

- operationId: `ingest_logs`
- summary: Ingest log records via OTLP/HTTP protobuf.
- description: Authenticates via API key in header, decompresses, decodes protobuf,
checks rate limit and storage quota, routes high-severity logs
to DB and all logs to S3.
- tags: `OTel Ingest`
- parameters: _(none)_
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Logs accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/metrics`

- operationId: `ingest_metrics`
- summary: Ingest metrics via OTLP/HTTP protobuf.
- description: Authenticates via API key in header, decompresses, decodes protobuf,
checks rate limit and storage quota, then stores.
- tags: `OTel Ingest`
- parameters: _(none)_
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Metrics accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/traces`

- operationId: `ingest_traces`
- summary: Ingest trace spans via OTLP/HTTP protobuf.
- description: Authenticates via API key in header, decompresses, decodes protobuf,
checks rate limit and storage quota, then stores spans.
- tags: `OTel Ingest`
- parameters: _(none)_
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Traces accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/{project_id}/{environment_id}/{deployment_id}/logs`

- operationId: `ingest_logs_by_path`
- summary: Ingest log records with project/environment/deployment in the URL path.
- tags: `OTel Ingest`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `environment_id` (path) *required*: `integer`
  - `deployment_id` (path) *required*: `integer`
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Logs accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/{project_id}/{environment_id}/{deployment_id}/metrics`

- operationId: `ingest_metrics_by_path`
- summary: Ingest metrics with project/environment/deployment in the URL path.
- tags: `OTel Ingest`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `environment_id` (path) *required*: `integer`
  - `deployment_id` (path) *required*: `integer`
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Metrics accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /otel/v1/{project_id}/{environment_id}/{deployment_id}/traces`

- operationId: `ingest_traces_by_path`
- summary: Ingest trace spans with project/environment/deployment in the URL path.
- tags: `OTel Ingest`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `environment_id` (path) *required*: `integer`
  - `deployment_id` (path) *required*: `integer`
- requestBody:
  - `application/x-protobuf`:
    - type: `string`
- responses:
  - `200`: Traces accepted (OTLP response in the request's encoding: protobuf, or `{}` for JSON)
  - `400`: Invalid payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Missing or invalid API key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Storage quota exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Rate limit exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /platform/access-info`

- operationId: `get_access_info`
- summary: Get information about how the service is being accessed
- description: Returns details about the server's access mode, public IP address, private IP address,
and domain creation capabilities. Both IP addresses are always included when available.
- tags: `Platform`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Service access information
    - `application/json`:
      - type: `object (5 properties)`
      - `access_mode` *required*: `string`
        - description: Mode of access: "local", "direct", "nat", or `"cloudflare_tunnel"`
        - type: `string`
      - `can_create_domains` *required*: `boolean`
        - description: Whether domain creation is allowed in this mode
        - type: `boolean`
      - `domain_creation_error`: `['string', 'null']`
        - description: Error message if domain creation is not allowed
        - type: `['string', 'null']`
      - `private_ip`: `['string', 'null']`
        - description: Server's private/local IP address (always returned if available)
        - type: `['string', 'null']`
      - `public_ip`: `['string', 'null']`
        - description: Server's public IP address (always returned if available)
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `GET /platform/private-ip`

- operationId: `get_private_ip`
- summary: Get private/local IP address of the server
- tags: `Platform`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved private IP address
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /platform/public-ip`

- operationId: `get_public_ip`
- summary: Get public IP address of the server
- tags: `Platform`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved public IP address
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /presets`

- operationId: `list_presets`
- summary: List all available presets
- tags: `Presets`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of available presets
    - `application/json`:
      - type: `object (2 properties)`
      - `presets` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /presets/{slug}/dockerfile`

- operationId: `generate_preset_dockerfile`
- summary: Generate a Dockerfile from a preset
- description: Returns the Dockerfile content and build arguments for a given preset slug.
The CLI can use this to build Docker images locally without needing a Dockerfile
in the project directory, enabling zero-config deployments.
- tags: `Presets`
- parameters:
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `build_command`: `['string', 'null']`
      - description: Custom build command (overrides preset default)
      - type: `['string', 'null']`
    - `install_command`: `['string', 'null']`
      - description: Custom install command (overrides preset default)
      - type: `['string', 'null']`
    - `output_dir`: `['string', 'null']`
      - description: Output directory for static builds
      - type: `['string', 'null']`
    - `package_manager`: `['string', 'null']`
      - description: Package manager used by the project (npm, yarn, pnpm, bun)
      - type: `['string', 'null']`
    - `project_name`: `['string', 'null']`
      - description: Project name/slug used for container naming
      - type: `['string', 'null']`
    - `use_buildkit`: `boolean`
      - description: Whether to use `BuildKit` cache mounts for faster builds
      - type: `boolean`
- responses:
  - `200`: Generated Dockerfile
    - `application/json`:
      - type: `object (3 properties)`
      - `build_args` *required*: `object`
        - description: Build arguments to pass to `docker build --build-arg KEY=VALUE`
        - type: `object`
      - `dockerfile` *required*: `string`
        - description: The generated Dockerfile content
        - type: `string`
      - `preset` *required*: `string`
        - description: The preset slug used for generation
        - type: `string`
  - `401`: Unauthorized
  - `404`: Preset not found
  - `500`: Internal server error

### `GET /preview-gateway/logs`

- operationId: `get_preview_gateway_logs`
- tags: `Preview Gateway`
- parameters:
  - `tail` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `lines` *required*: `array<string>`
        - type: `array<string>`

### `POST /preview-gateway/restart`

- operationId: `restart_preview_gateway`
- tags: `Preview Gateway`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `204`: Gateway restarted

### `GET /preview-gateway/settings`

- operationId: `get_preview_gateway_settings`
- tags: `Preview Gateway`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `auto_upgrade` *required*: `boolean`
        - type: `boolean`
      - `default_host_port` *required*: `integer`
        - description: The compile-time default host port.
        - type: `integer`
      - `default_image` *required*: `string`
        - description: The compile-time default image — exposed so the UI can offer a
        - type: `string`
      - `host_port` *required*: `integer`
        - type: `integer`
      - `image` *required*: `string`
        - type: `string`

### `PATCH /preview-gateway/settings`

- operationId: `patch_preview_gateway_settings`
- tags: `Preview Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `auto_upgrade`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `host_port`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `image`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `auto_upgrade` *required*: `boolean`
        - type: `boolean`
      - `default_host_port` *required*: `integer`
        - description: The compile-time default host port.
        - type: `integer`
      - `default_image` *required*: `string`
        - description: The compile-time default image — exposed so the UI can offer a
        - type: `string`
      - `host_port` *required*: `integer`
        - type: `integer`
      - `image` *required*: `string`
        - type: `string`

### `GET /preview-gateway/status`

- operationId: `get_preview_gateway_status`
- tags: `Preview Gateway`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (15 properties)`
      - `auto_upgrade` *required*: `boolean`
        - description: True if `auto_upgrade` is enabled in settings.
        - type: `boolean`
      - `container_name` *required*: `string`
        - description: Container name.
        - type: `string`
      - `drift` *required*: `boolean`
        - description: True when `image != expected_image` and the container is present.
        - type: `boolean`
      - `expected_image` *required*: `string`
        - description: The image the supervisor *expects* (from settings/constant). If this
        - type: `string`
      - `health` *required*: `string`
        - description: Higher-level health label: "running" | "restarting" | `"crash_looping"`
        - type: `string`
      - `host_port`: `['integer', 'null']`
        - description: Host port that the container's :8080 is published on.
        - type: `['integer', 'null']`
      - `image`: `['string', 'null']`
        - description: Image reference the container was created with (e.g.
        - type: `['string', 'null']`
      - `image_digest`: `['string', 'null']`
        - description: Image digest if available (e.g. `sha256:…`).
        - type: `['string', 'null']`
      - `last_error`: `['string', 'null']`
        - description: Error string Docker recorded for the container (e.g. startup failure).
        - type: `['string', 'null']`
      - `last_exit_code`: `['integer', 'null']`
        - description: Exit code of the last run, if the container is not currently running.
        - type: `['integer', 'null']`
      - `network`: `['string', 'null']`
        - description: The gateway's own network when it is attached (`conusai-preview-gateway-net`),
        - type: `['string', 'null']`
      - `present` *required*: `boolean`
        - description: Whether the container exists at all.
        - type: `boolean`
      - `restart_count`: `['integer', 'null']`
        - description: Number of times Docker has restarted the container.
        - type: `['integer', 'null']`
      - `running` *required*: `boolean`
        - description: Whether the container is currently running.
        - type: `boolean`
      - `started_at`: `['string', 'null']`
        - description: ISO 8601 timestamp the container was started at, if running.
        - type: `['string', 'null']`

### `POST /preview-gateway/upgrade`

- operationId: `upgrade_preview_gateway`
- tags: `Preview Gateway`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `image` *required*: `string`
      - description: Image reference to pull and run (e.g.
      - type: `string`
- responses:
  - `204`: Gateway upgraded

### `GET /projects/{id}/deployments`

- operationId: `get_project_deployments`
- summary: Lists deployments for a project, paginated and optionally filtered by environment.
- tags: `Projects`
- parameters:
  - `id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of deployments
    - `application/json`:
      - type: `object (4 properties)`
      - `deployments` *required*: `array<object (21 properties)>`
        - type: `array<object (21 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `404`: Project not found

### `POST /projects/{project_id}/agents/runs/{run_id}/reports`

- operationId: `report_agent_run`
- tags: `Agents`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `message` *required*: `string`
      - type: `string`
- responses:
  - `204`: No Content
  - `403`: Forbidden
  - `404`: Not Found

### `GET /projects/{project_id}/autofixer/runs/{run_id}`

- operationId: `get_run`
- summary: Get a single autofixer run with its logs.
- tags: `Autofixer`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Run with logs
    - `application/json`:
      - type: `object (2 properties)`
      - `logs` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `run` *required*: `object (21 properties)`
        - type: `object (21 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found
  - `500`: Internal server error

### `POST /projects/{project_id}/autofixer/runs/{run_id}/add-context`

- operationId: `add_context`
- summary: Append a user message to the run's context field.
- tags: `Autofixer`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `message` *required*: `string`
      - type: `string`
- responses:
  - `200`: Context appended
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found
  - `500`: Internal server error

### `POST /projects/{project_id}/autofixer/runs/{run_id}/create-pr`

- operationId: `create_pr`
- summary: Push the fix branch and create a pull request.
Requires phase == `"fix_ready"`.
- tags: `Autofixer`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `201`: PR created
    - `application/json`:
      - type: `object (4 properties)`
      - `branch_name` *required*: `string`
        - type: `string`
      - `pr_number` *required*: `integer`
        - type: `integer`
      - `pr_url` *required*: `string`
        - type: `string`
      - `run` *required*: `object (21 properties)`
        - type: `object (21 properties)`
  - `400`: Run not in fix_ready phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found
  - `500`: Internal server error

### `POST /projects/{project_id}/autofixer/runs/{run_id}/fix`

- operationId: `start_fix`
- summary: Transition from analysis to fix phase.
Requires phase == "analyzed".
- tags: `Autofixer`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Fix generation started
  - `400`: Run not in analyzed phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found
  - `500`: Internal server error

### `POST /projects/{project_id}/autofixer/runs/{run_id}/re-analyze`

- operationId: `re_analyze`
- summary: Continue the conversation with user feedback.
Uses the same Claude session (--continue) in the existing work directory.
Requires phase == "analyzed".
- tags: `Autofixer`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Conversation continued with feedback
  - `400`: Run not in analyzed phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found
  - `500`: Internal server error

### `GET /projects/{project_id}/environments`

- operationId: `get_environments`
- summary: Get all environments for a project
- tags: `Projects`
- parameters:
  - `project_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of environments
    - `application/json`:
      - type: `array<object (18 properties)>`
  - `404`: Project not found
  - `500`: Internal server error

### `GET /projects/{project_id}/secrets`

- operationId: `listProjectSecrets`
- summary: List project secrets (metadata only — values never returned).
- tags: `Secrets`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of secrets (metadata only, no values)
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `404`: Project not found
  - `500`: Internal server error

### `POST /projects/{project_id}/secrets`

- operationId: `createProjectSecret`
- summary: Create a new secret. The value is encrypted before storage and will be
mounted as a file at `/run/secrets/<KEY>` on the next deployment.
The plaintext value is NOT returned — the response carries only metadata.
- tags: `Secrets`
- parameters:
  - `project_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `environment_ids`: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - description: Include this secret in preview environments.
      - type: `boolean`
    - `key` *required*: `string`
      - description: Identifier for the secret. Becomes the filename at `/run/secrets/<KEY>`.
      - type: `string`
    - `value` *required*: `string`
      - description: Plaintext value, <= 1 MiB.
      - type: `string`
- responses:
  - `201`: Secret created
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid key or value too large
  - `409`: Key already exists in project
  - `500`: Internal server error

### `PUT /projects/{project_id}/secrets/{secret_id}`

- operationId: `updateProjectSecret`
- summary: Update a project secret. Value rotation requires a redeploy to take effect —
running containers keep their currently-mounted values until the next
deployment.
- tags: `Secrets`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `secret_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `environment_ids`: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - type: `boolean`
    - `value`: `['string', 'null']`
      - description: New plaintext value, <= 1 MiB. Omit to keep the existing value.
      - type: `['string', 'null']`
- responses:
  - `200`: Secret updated
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Value too large
  - `404`: Secret not found
  - `500`: Internal server error

### `DELETE /projects/{project_id}/secrets/{secret_id}`

- operationId: `deleteProjectSecret`
- summary: Delete a project secret. Running containers keep their mounted secret files
until they are redeployed.
- tags: `Secrets`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `secret_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Secret deleted
  - `404`: Secret not found
  - `500`: Internal server error

### `GET /proxy-logs`

- operationId: `get_proxy_logs`
- summary: Get proxy logs with optional filters and pagination
- tags: `Proxy Logs`
- parameters:
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `deployment_id` (query): `['integer', 'null']`
  - `session_id` (query): `['integer', 'null']`
  - `visitor_id` (query): `['integer', 'null']`
  - `start_date` (query): `['string', 'null']`
  - `end_date` (query): `['string', 'null']`
  - `method` (query): `['string', 'null']`
  - `host` (query): `['string', 'null']`
  - `path` (query): `['string', 'null']`
  - `client_ip` (query): `['string', 'null']`
  - `status_code` (query): `['integer', 'null']`
  - `response_time_min` (query): `['integer', 'null']`
  - `response_time_max` (query): `['integer', 'null']`
  - `routing_status` (query): `['string', 'null']`
  - `request_source` (query): `['string', 'null']`
  - `is_system_request` (query): `['boolean', 'null']`
  - `user_agent` (query): `['string', 'null']`
  - `browser` (query): `['string', 'null']`
  - `operating_system` (query): `['string', 'null']`
  - `device_type` (query): `['string', 'null']`
  - `is_bot` (query): `['boolean', 'null']`
  - `exclude_bots` (query): `['boolean', 'null']`
  - `bot_name` (query): `['string', 'null']`
  - `ai_provider` (query): `['string', 'null']`
  - `ai_agent` (query): `['string', 'null']`
  - `is_ai_agent` (query): `['boolean', 'null']`
  - `request_size_min` (query): `['integer', 'null']`
  - `request_size_max` (query): `['integer', 'null']`
  - `response_size_min` (query): `['integer', 'null']`
  - `response_size_max` (query): `['integer', 'null']`
  - `cache_status` (query): `['string', 'null']`
  - `container_id` (query): `['string', 'null']`
  - `upstream_host` (query): `['string', 'null']`
  - `has_error` (query): `['boolean', 'null']`
  - `request_id` (query): `['string', 'null']`
  - `trace_id` (query): `['string', 'null']`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of proxy logs
    - `application/json`:
      - type: `object (5 properties)`
      - `logs` *required*: `array<object (33 properties)>`
        - type: `array<object (33 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
      - `total_pages` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/ai-agents/known`

- operationId: `list_known_ai_agents`
- summary: List every AI agent the detector knows how to classify.
- description: Returned in the same order as the internal taxonomy so the UI can use it as
a stable dropdown.
- tags: `Proxy Logs`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Known AI agents
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/request/{request_id}`

- operationId: `get_proxy_log_by_request_id`
- summary: Get a proxy log by request ID (for tracing)
- tags: `Proxy Logs`
- parameters:
  - `request_id` (path) *required*: `string`
  - `timestamp` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Proxy log found
    - `application/json`:
      - type: `object (33 properties)`
      - `bot_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `browser`: `['string', 'null']`
        - type: `['string', 'null']`
      - `browser_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cache_status`: `['string', 'null']`
        - type: `['string', 'null']`
      - `client_ip`: `['string', 'null']`
        - type: `['string', 'null']`
      - `container_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `device_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `host` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_geolocation_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `is_bot` *required*: `boolean`
        - type: `boolean`
      - `is_system_request` *required*: `boolean`
        - type: `boolean`
      - `method` *required*: `string`
        - type: `string`
      - `operating_system`: `['string', 'null']`
        - type: `['string', 'null']`
      - `path` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `query_string`: `['string', 'null']`
        - type: `['string', 'null']`
      - `referrer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `request_id` *required*: `string`
        - type: `string`
      - `request_size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `request_source` *required*: `string`
        - type: `string`
      - `response_size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `response_time_ms`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `routing_status` *required*: `string`
        - type: `string`
      - `session_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status_code` *required*: `integer`
        - type: `integer`
      - `timestamp` *required*: `string`
        - type: `string`
      - `upstream_host`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_agent`: `['string', 'null']`
        - type: `['string', 'null']`
      - `visitor_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Proxy log not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/ai-agent-pages`

- operationId: `get_ai_agent_pages`
- summary: Get the top pages accessed by a specific AI agent over a time window.
- description: Returns page paths ranked by request count, scoped to a single canonical
agent name (e.g. `ChatGPT-User`). Use `GET /proxy-logs/ai-agents/known` to
list all valid agent names. Unknown agent names return an empty items array.
- tags: `Proxy Logs`
- parameters:
  - `agent` (query) *required*: `string`
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Pages breakdown for the requested agent
    - `application/json`:
      - type: `object (4 properties)`
      - `agent` *required*: `string`
        - description: The agent name this breakdown is scoped to.
        - type: `string`
      - `end_time` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/ai-agents`

- operationId: `get_ai_agent_breakdown`
- summary: Get the per-AI-agent breakdown for a project over a time window.
- tags: `Proxy Logs`
- parameters:
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `path` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: AI agent breakdown
    - `application/json`:
      - type: `object (3 properties)`
      - `end_time` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/ai-agents/timeline`

- operationId: `get_ai_agent_timeline`
- summary: Time-bucketed AI-agent request volume, split by provider or agent.
- description: Powers the "AI agents over time" stacked chart. Same data source as the AI
agent breakdown (request logs), just bucketed.
- tags: `Proxy Logs`
- parameters:
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `group_by` (query): `['string', 'null']`
  - `bucket` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: AI agent timeline
    - `application/json`:
      - type: `object (5 properties)`
      - `bucket` *required*: `string`
        - description: Bucket interval used for the buckets (so the UI can label the x-axis).
        - type: `string`
      - `end_time` *required*: `string`
        - type: `string`
      - `group_by` *required*: `string`
        - description: Echoes the grouping dimension actually applied.
        - type: `string`
      - `items` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/ai-pages`

- operationId: `get_ai_page_breakdown`
- summary: Get the top pages crawled by AI agents over a time window.
- tags: `Proxy Logs`
- parameters:
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `path` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: AI page breakdown
    - `application/json`:
      - type: `object (3 properties)`
      - `end_time` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/ai-status`

- operationId: `get_ai_status_breakdown`
- summary: HTTP status-class breakdown for AI-agent traffic — are bots being served
(2xx) or hitting broken/blocked pages (4xx/5xx)?
- tags: `Proxy Logs`
- parameters:
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `path` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: AI status breakdown
    - `application/json`:
      - type: `object (3 properties)`
      - `end_time` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `start_time` *required*: `string`
        - type: `string`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/projects-health`

- operationId: `get_projects_health`
- summary: Get health summaries for multiple projects (last 1 hour)
- tags: `Proxy Logs`
- parameters:
  - `project_ids` (query) *required*: `string`
  - `start_time` (query): `['string', 'null']`
  - `end_time` (query): `['string', 'null']`
  - `is_bot` (query): `['boolean', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Health summaries per project
    - `application/json`:
      - type: `object (1 properties)`
      - `projects` *required*: `object`
        - description: Health summaries keyed by project ID
        - type: `object`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/time-buckets`

- operationId: `get_time_bucket_stats`
- summary: Get time-bucketed statistics with optional filters
- tags: `Proxy Logs`
- parameters:
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
  - `bucket_interval` (query): `string`
  - `method` (query): `string`
  - `client_ip` (query): `string`
  - `project_id` (query): `integer`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `host` (query): `string`
  - `status_code` (query): `integer`
  - `status_code_class` (query): `string`
  - `routing_status` (query): `string`
  - `request_source` (query): `string`
  - `is_bot` (query): `boolean`
  - `device_type` (query): `string`
  - `has_project` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Time-bucketed statistics
    - `application/json`:
      - type: `object (4 properties)`
      - `bucket_interval` *required*: `string`
        - type: `string`
      - `end_time` *required*: `string`
        - type: `string`
      - `start_time` *required*: `string`
        - type: `string`
      - `stats` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/stats/today`

- operationId: `get_today_stats`
- summary: Get today's request count with optional filters
- tags: `Proxy Logs`
- parameters:
  - `method` (query): `['string', 'null']`
  - `client_ip` (query): `['string', 'null']`
  - `project_id` (query): `['integer', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `deployment_id` (query): `['integer', 'null']`
  - `host` (query): `['string', 'null']`
  - `status_code` (query): `['integer', 'null']`
  - `status_code_class` (query): `['string', 'null']`
  - `routing_status` (query): `['string', 'null']`
  - `request_source` (query): `['string', 'null']`
  - `is_bot` (query): `['boolean', 'null']`
  - `device_type` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Today's request count
    - `application/json`:
      - type: `object (2 properties)`
      - `date` *required*: `string`
        - description: Date for which stats are returned
        - type: `string`
      - `total_requests` *required*: `integer`
        - description: Total requests today
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /proxy-logs/{id}`

- operationId: `get_proxy_log_by_id`
- summary: Get a single proxy log by ID
- tags: `Proxy Logs`
- parameters:
  - `id` (path) *required*: `integer`
  - `timestamp` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Proxy log found
    - `application/json`:
      - type: `object (33 properties)`
      - `bot_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `browser`: `['string', 'null']`
        - type: `['string', 'null']`
      - `browser_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cache_status`: `['string', 'null']`
        - type: `['string', 'null']`
      - `client_ip`: `['string', 'null']`
        - type: `['string', 'null']`
      - `container_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `device_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `host` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_geolocation_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `is_bot` *required*: `boolean`
        - type: `boolean`
      - `is_system_request` *required*: `boolean`
        - type: `boolean`
      - `method` *required*: `string`
        - type: `string`
      - `operating_system`: `['string', 'null']`
        - type: `['string', 'null']`
      - `path` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `query_string`: `['string', 'null']`
        - type: `['string', 'null']`
      - `referrer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `request_id` *required*: `string`
        - type: `string`
      - `request_size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `request_source` *required*: `string`
        - type: `string`
      - `response_size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `response_time_ms`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `routing_status` *required*: `string`
        - type: `string`
      - `session_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status_code` *required*: `integer`
        - type: `integer`
      - `timestamp` *required*: `string`
        - type: `string`
      - `upstream_host`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_agent`: `['string', 'null']`
        - type: `['string', 'null']`
      - `visitor_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Proxy log not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /rdap/{target}`

- operationId: `get_rdap`
- summary: Get RDAP information for an IP or domain
- tags: `geo`
- parameters:
  - `target` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: RDAP information retrieved
    - `application/json`:
      - type: `any`
  - `400`: Invalid target
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Authentication required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `502`: External service error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /repositories/{repository_id}/preset/live`

- operationId: `get_repository_preset_live`
- tags: `Git Providers`
- parameters:
  - `repository_id` (path) *required*: `integer`
  - `branch` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Repository presets calculated successfully - includes root preset and projects in subdirectories
    - `application/json`:
      - type: `object (5 properties)`
      - `calculated_at` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `presets` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `repository_id` *required*: `integer`
        - type: `integer`
  - `400`: Bad request
  - `404`: Repository not found
  - `500`: Internal server error

### `GET /revenue/events`

- operationId: `revenue_global_events`
- summary: Org-wide revenue events across every project. Powers the revenue
transactions page. Supports filtering by project, date range, and
event type.
- tags: `Revenue`
- parameters:
  - `project_id` (query): `integer`
  - `from` (query): `string`
  - `to` (query): `string`
  - `event_types` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (9 properties)>`

### `GET /revenue/providers`

- operationId: `revenue_list_providers`
- summary: List registered providers (what the UI needs to render the "Connect"
dropdown + its wizard instructions).
- tags: `Revenue`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (3 properties)>`

### `GET /reverse-dns/{ip}`

- operationId: `get_reverse_dns`
- summary: Get reverse DNS for an IP address
- tags: `geo`
- parameters:
  - `ip` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Reverse DNS records retrieved
    - `application/json`:
      - type: `any`
  - `400`: Invalid IP address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Authentication required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /services/available-containers`

- operationId: `list_available_containers`
- summary: List available Docker containers that can be imported as services
- tags: `Services`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of available containers
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Platform administrator required
  - `500`: Internal server error

### `GET /session-replays`

- operationId: `get_project_session_replays`
- summary: Get session replays for a project
- tags: `Analytics`
- parameters:
  - `project_id` (query) *required*: `integer`
  - `environment_id` (query): `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Session replays retrieved successfully
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `sessions` *required*: `array<object (30 properties)>`
        - type: `array<object (30 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `400`: Bad request
    - `application/json`:
      - type: `object (2 properties)`
      - `details`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error` *required*: `string`
        - type: `string`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (2 properties)`
      - `details`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error` *required*: `string`
        - type: `string`

### `GET /settings`

- operationId: `get_settings`
- summary: Get application settings
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Application settings with masked sensitive fields
    - `application/json`:
      - type: `object (26 properties)`
      - `agent_sandbox` *required*: `object (11 properties)`
        - description: Agent sandbox settings with masked per-provider credentials.
        - type: `object (11 properties)`
      - `ai_config` *required*: `object (2 properties)`
        - description: Global AI configuration settings. Controls the default config repo
        - type: `object (2 properties)`
      - `apps_base` *required*: `string`
        - type: `string`
      - `build_limits` *required*: `object (3 properties)`
        - description: Control-plane build resource limits.
        - type: `object (3 properties)`
      - `cluster_dns` *required*: `object (1 properties)`
        - description: Cluster-DNS resolver settings (ADR-024, experimental beta).
        - type: `object (1 properties)`
      - `container_logs` *required*: `object (4 properties)`
        - description: Docker container log rotation settings
        - type: `object (4 properties)`
      - `dashboard_base` *required*: `string`
        - type: `string`
      - `disk_space_alert` *required*: `object (4 properties)`
        - description: Disk space alert settings for monitoring disk usage
        - type: `object (4 properties)`
      - `dns_provider` *required*: `object (2 properties)`
        - description: DNS provider settings with masked sensitive fields
        - type: `object (2 properties)`
      - `docker_registry` *required*: `object (6 properties)`
        - description: Docker registry settings with masked sensitive fields
        - type: `object (6 properties)`
      - `effective_metrics_store` *required*: `string`
        - description: Which storage backend to use for the `MetricsStore`.
        - type: `string`
      - `external_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `insecure_tls` *required*: `boolean`
        - type: `boolean`
      - `internal_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `letsencrypt` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `monitoring` *required*: `object (7 properties)`
        - description: Monitoring settings with the `ClickHouse` DSN masked.
        - type: `object (7 properties)`
      - `multi_node` *required*: `object (8 properties)`
        - description: Multi-node settings with `join_token_hash` elided.
        - type: `object (8 properties)`
      - `notifications` *required*: `object (4 properties)`
        - description: Rate limits and sandbox switch for outbound notifications.
        - type: `object (4 properties)`
      - `preview_domain` *required*: `string`
        - type: `string`
      - `preview_gateway` *required*: `object (4 properties)`
        - description: Preview gateway settings with `shared_secret` elided.
        - type: `object (4 properties)`
      - `rate_limiting` *required*: `object (5 properties)`
        - type: `object (5 properties)`
      - `require_mfa_for_admins` *required*: `boolean`
        - description: When enabled, Admin-role accounts without MFA enrolled are rejected
        - type: `boolean`
      - `screenshots` *required*: `object (3 properties)`
        - type: `object (3 properties)`
      - `security_headers` *required*: `object (9 properties)`
        - type: `object (9 properties)`
      - `setup_complete` *required*: `boolean`
        - description: Whether `conusai setup` has been run at least once. The web onboarding
        - type: `boolean`
      - `telemetry_endpoint` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `500`: Internal server error

### `PUT /settings`

- operationId: `update_settings`
- summary: Update application settings
- tags: `Settings`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (33 properties)`
    - `agent_sandbox`: `object (11 properties)`
      - description: Global agent sandbox settings. Controls whether agent runs are isolated
      - type: `object (11 properties)`
    - `ai_config`: `object (2 properties)`
      - description: Global AI configuration settings. Controls the default config repo
      - type: `object (2 properties)`
    - `apps_base`: `string`
      - description: Separate registrable apex for deployed tenant apps
      - type: `string`
    - `build_limits`: `object (3 properties)`
      - description: Control-plane build resource limits.
      - type: `object (3 properties)`
    - `cluster_dns`: `object (1 properties)`
      - description: Cluster-DNS resolver settings (ADR-024, experimental beta).
      - type: `object (1 properties)`
    - `console_version`: `['string', 'null']`
      - description: Binary version tag (e.g. "v0.1.0") of the *console* process
      - type: `['string', 'null']`
    - `container_logs`: `object (4 properties)`
      - description: Docker container log rotation settings
      - type: `object (4 properties)`
    - `dashboard_base`: `string`
      - description: Base domain for the dashboard / console / API and per-org dashboard hosts
      - type: `string`
    - `disk_space_alert`: `object (4 properties)`
      - description: Disk space alert settings for monitoring disk usage
      - type: `object (4 properties)`
    - `dns_provider`: `object (2 properties)`
      - type: `object (2 properties)`
    - `docker_registry`: `object (6 properties)`
      - type: `object (6 properties)`
    - `edge_target`: `['string', 'null']`
      - description: Public edge target that generated DNS records point at when a managed
      - type: `['string', 'null']`
    - `external_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `insecure_tls`: `boolean`
      - description: Skip TLS certificate verification on outbound HTTP clients built by the
      - type: `boolean`
    - `internal_url`: `['string', 'null']`
      - description: URL that service containers use to reach the `ConusAI` API from *inside*
      - type: `['string', 'null']`
    - `letsencrypt`: `object (2 properties)`
      - type: `object (2 properties)`
    - `metering_endpoint`: `string`
      - description: `ConusAI` licensing-metering ingest endpoint. Empty string means "use the
      - type: `string`
    - `monitoring`: `object (7 properties)`
      - description: Global metrics observability configuration.
      - type: `object (7 properties)`
    - `multi_node`: `object (13 properties)`
      - description: Multi-node cluster settings
      - type: `object (13 properties)`
    - `notifications`: `object (4 properties)`
      - description: Rate limits and sandbox switch for outbound notifications.
      - type: `object (4 properties)`
    - `observability_compression`: `object (2 properties)`
      - description: `TimescaleDB` compression policy configuration for append-only observability
      - type: `object (2 properties)`
    - `observability_retention`: `object (4 properties)`
      - description: Retention policy configuration for raw observability tables. Values are in
      - type: `object (4 properties)`
    - `on_demand_tls`: `object (5 properties)`
      - description: On-demand (lazy) HTTP-01 TLS issuance settings (ADR-018).
      - type: `object (5 properties)`
    - `platform_domain_aliases`: `array<string>`
      - description: Additional console apexes, each with its own on-demand cert (H4.4).
      - type: `array<string>`
    - `preview_domain`: `string`
      - type: `string`
    - `preview_gateway`: `object (4 properties)`
      - description: Workspace preview gateway settings.
      - type: `object (4 properties)`
    - `rate_limiting`: `object (5 properties)`
      - type: `object (5 properties)`
    - `require_mfa_for_admins`: `boolean`
      - description: When `true`, any user holding the `Admin` role must have MFA enrolled
      - type: `boolean`
    - `screenshots`: `object (3 properties)`
      - type: `object (3 properties)`
    - `security_headers`: `object (9 properties)`
      - type: `object (9 properties)`
    - `setup_complete`: `boolean`
      - description: Set to `true` by `conusai setup` (all modes) once initial configuration
      - type: `boolean`
    - `shared_app_domain`: `boolean`
      - description: The operator accepted that tenant apps share the console's registrable
      - type: `boolean`
    - `telemetry_endpoint`: `string`
      - description: Anonymous product-telemetry ingest endpoint. Empty string means "use
      - type: `string`
- responses:
  - `200`: Settings updated successfully
    - `application/json`:
      - type: `object (1 properties)`
      - `message` *required*: `string`
        - type: `string`
  - `400`: Bad request - invalid settings
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /settings/agent-token`

- operationId: `save_agent_token`
- summary: Save an encrypted AI provider token for use in sandbox containers.
- tags: `Agents`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `token` *required*: `string`
      - description: The OAuth token from `claude setup-token` or an API key.
      - type: `string`
- responses:
  - `200`: Token encrypted and persisted
    - `application/json`:
      - type: `object (1 properties)`
      - `saved` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Encryption or database error

### `GET /settings/ai-providers`

- operationId: `list_ai_providers`
- summary: List the AI provider catalog. Includes per-provider "is a credential
configured?" so the settings UI can render configured/not-configured
badges without leaking the encrypted credential.
- tags: `Agents`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `default_provider` *required*: `string`
        - description: Active provider id from `agent_sandbox.default_provider`. The settings
        - type: `string`
      - `providers` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
  - `401`: Unauthorized

### `PATCH /settings/ai-providers/{provider_id}`

- operationId: `update_ai_provider`
- summary: Update provider-scoped settings without touching the saved credential.
Today that means just `default_model`; future per-provider settings
(base URL overrides, request headers, etc.) can land here too without
changing the shape of `save_credential`.
- tags: `Agents`
- parameters:
  - `provider_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `default_model`: `['string', 'null']`
      - description: New default model id. `None` or an empty string clears the stored
      - type: `['string', 'null']`
    - `max_turns_analysis`: `['integer', 'null']`
      - description: Default max turns for the autofixer analysis phase (1–200). `0`
      - type: `['integer', 'null']`
    - `max_turns_feedback`: `['integer', 'null']`
      - description: Default max turns for autofixer feedback rounds (1–200). `0` clears;
      - type: `['integer', 'null']`
    - `max_turns_fix`: `['integer', 'null']`
      - description: Default max turns for the autofixer fix phase (1–200). `0` clears;
      - type: `['integer', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `default_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `max_turns_analysis`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_turns_feedback`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_turns_fix`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `provider_id` *required*: `string`
        - type: `string`
  - `400`: Unknown provider
  - `401`: Unauthorized

### `POST /settings/ai-providers/{provider_id}/activate`

- operationId: `activate_ai_provider`
- summary: Activate a provider as the platform-wide default. Refuses to activate a
provider that doesn't have a credential saved yet — the UI enforces the
same rule on the button, but we re-check server-side so a stale tab
can't bypass it.
- tags: `Agents`
- parameters:
  - `provider_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `default_provider` *required*: `string`
        - type: `string`
  - `400`: Provider not configured
  - `401`: Unauthorized

### `POST /settings/ai-providers/{provider_id}/credential`

- operationId: `save_ai_provider_credential`
- summary: Save (or replace) a provider's credential. The credential is encrypted
with `EncryptionService` and stored inside
`agent_sandbox.providers[provider_id].credentials_encrypted`.
- description: The plaintext shape depends on the flavor's `credential_format`:
  - `ApiKey` / `OauthToken`: the key/token string.
  - `ConfigFile`: the full file body (e.g. `OpenCode`'s `auth.json`).
- tags: `Agents`
- parameters:
  - `provider_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `auth_type` *required*: `string`
      - description: Auth flavor id (must match one of the provider's catalog entries).
      - type: `string`
    - `credential` *required*: `string`
      - description: Plaintext credential body (API key, OAuth token, or full config file
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `auth_type` *required*: `string`
        - type: `string`
      - `provider_id` *required*: `string`
        - type: `string`
      - `saved` *required*: `boolean`
        - type: `boolean`
  - `400`: Validation error
  - `401`: Unauthorized

### `GET /settings/disk-status`

- operationId: `get_disk_status`
- summary: Get current disk usage for the control-plane server
- description: Returns live disk usage for the monitored path along with any disks that
meet or exceed the configured alert threshold. Read-only — does not send
notifications. Used by the dashboard to surface a low-disk-space warning.
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Current disk usage and threshold alerts
    - `application/json`:
      - type: `object (5 properties)`
      - `alerts` *required*: `array<object (5 properties)>`
        - description: Disks that meet or exceed the threshold
        - type: `array<object (5 properties)>`
      - `checked_at` *required*: `string`
        - description: Timestamp of the check (ISO 8601, UTC)
        - type: `string`
      - `disks` *required*: `array<object (6 properties)>`
        - description: List of all monitored disks
        - type: `array<object (6 properties)>`
      - `enabled` *required*: `boolean`
        - description: Whether disk space monitoring is enabled in settings
        - type: `boolean`
      - `threshold_percent` *required*: `integer`
        - description: Configured alert threshold percentage (0-100)
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /settings/enrollment-tokens`

- operationId: `list_enrollment_tokens`
- summary: List currently-valid node enrollment tokens (hashes elided).
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Active enrollment tokens
    - `application/json`:
      - type: `object (1 properties)`
      - `tokens` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `POST /settings/enrollment-tokens`

- operationId: `mint_enrollment_token`
- summary: Mint a short-lived, single-use node enrollment token.
- tags: `Settings`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `bound_node_name`: `['string', 'null']`
      - description: Optional: restrict the token to register one specific node name.
      - type: `['string', 'null']`
    - `max_uses`: `['integer', 'null']`
      - description: Maximum registrations this token may authorize (default 1).
      - type: `['integer', 'null']`
    - `ttl_secs`: `['integer', 'null']`
      - description: Time-to-live in seconds (default 3600 = 1h).
      - type: `['integer', 'null']`
- responses:
  - `200`: Enrollment token minted
    - `application/json`:
      - type: `object (6 properties)`
      - `ca_fingerprint`: `['string', 'null']`
        - description: SHA-256 fingerprint of the cluster CA (if mTLS is set up). Pass it to the
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `max_uses` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `token` *required*: `string`
        - description: The plaintext enrollment token — shown only once, save it now.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `DELETE /settings/enrollment-tokens/{id}`

- operationId: `revoke_enrollment_token`
- summary: Revoke a node enrollment token by id.
- tags: `Settings`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Enrollment token revoked
    - `application/json`:
      - type: `object (1 properties)`
      - `message` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Enrollment token not found
  - `500`: Internal server error

### `DELETE /settings/join-token`

- operationId: `revoke_join_token`
- summary: Revoke the current join token
- description: Removes the stored join token hash, allowing any node to register
(if no other authentication is in place).
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Join token revoked
    - `application/json`:
      - type: `object (1 properties)`
      - `message` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `POST /settings/join-token/generate`

- operationId: `generate_join_token`
- summary: Generate a new join token for multi-node cluster registration
- description: Creates a random 32-byte hex token, stores the SHA-256 hash in settings,
and returns the plaintext exactly once. If a token already exists, it is replaced.
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Join token generated
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `token` *required*: `string`
        - description: The plaintext join token — shown only once, save it now
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `GET /settings/join-token/status`

- operationId: `get_join_token_status`
- summary: Check whether a join token is currently configured
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Join token status
    - `application/json`:
      - type: `object (1 properties)`
      - `has_token` *required*: `boolean`
        - description: Whether a join token has been configured
        - type: `boolean`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /settings/routes/refresh`

- operationId: `refresh_route_table`
- summary: Manually refresh the proxy route table
- description: Reloads all routes from the database into the in-memory proxy cache.
Useful as a workaround when routes are out of sync.
- tags: `Settings`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Route table refreshed
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - description: Human-readable message
        - type: `string`
      - `route_count` *required*: `integer`
        - description: Number of routes loaded
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `500`: Internal server error

### `POST /settings/sandbox-rebuild`

- operationId: `rebuild_sandbox_image`
- tags: `Agents`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Server-Sent Events stream of rebuild progress; final event `{"type":"done","success":bool,...}`
    - `text/event-stream`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /settings/sandbox-status`

- operationId: `get_global_sandbox_status`
- tags: `Agents`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Global sandbox readiness for the settings page
    - `application/json`:
      - type: `object (5 properties)`
      - `docker_available` *required*: `boolean`
        - type: `boolean`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `firecracker_available` *required*: `boolean`
        - type: `boolean`
      - `image_name` *required*: `string`
        - type: `string`
      - `image_ready` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /templates`

- operationId: `list_project_templates`
- summary: List all available templates
- description: Returns a list of all public templates, optionally filtered by tag or featured status.
- tags: `Templates`
- parameters:
  - `tag` (query): `string`
  - `featured` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: List of templates
    - `application/json`:
      - type: `object (2 properties)`
      - `templates` *required*: `array<object (15 properties)>`
        - description: List of templates
        - type: `array<object (15 properties)>`
      - `total` *required*: `integer`
        - description: Total number of templates
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /templates/tags`

- operationId: `list_project_template_tags`
- summary: List all available template tags
- description: Returns a list of all unique tags used by public templates.
- tags: `Templates`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of tags
    - `application/json`:
      - type: `object (2 properties)`
      - `tags` *required*: `array<string>`
        - description: List of available tags
        - type: `array<string>`
      - `total` *required*: `integer`
        - description: Total number of tags
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /templates/{slug}`

- operationId: `get_project_template`
- summary: Get a specific template by slug
- description: Returns detailed information about a single template.
- tags: `Templates`
- parameters:
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Template details
    - `application/json`:
      - type: `object (15 properties)`
      - `description`: `['string', 'null']`
        - description: Short description
        - type: `['string', 'null']`
      - `env_vars` *required*: `array<object (6 properties)>`
        - description: Environment variables template
        - type: `array<object (6 properties)>`
      - `exposed_port`: `['integer', 'null']`
        - description: Container port the prebuilt image listens on (image deploys only).
        - type: `['integer', 'null']`
      - `features` *required*: `array<string>`
        - description: Feature highlights
        - type: `array<string>`
      - `health_check_path`: `['string', 'null']`
        - description: HTTP health-check path probed after the container starts (image deploys).
        - type: `['string', 'null']`
      - `image`: `['string', 'null']`
        - description: Prebuilt Docker image reference. When set, the one-click deploy pulls and
        - type: `['string', 'null']`
      - `image_url`: `['string', 'null']`
        - description: URL to template image/icon
        - type: `['string', 'null']`
      - `is_featured` *required*: `boolean`
        - description: Whether the template is featured/promoted
        - type: `boolean`
      - `name` *required*: `string`
        - description: Display name
        - type: `string`
      - `preset` *required*: `string`
        - description: Framework/preset to use
        - type: `string`
      - `screenshot_url`: `['string', 'null']`
        - description: URL to a wide screenshot/banner preview of the deployed template.
        - type: `['string', 'null']`
      - `services` *required*: `array<string>`
        - description: Required managed services
        - type: `array<string>`
      - `slug` *required*: `string`
        - description: Unique identifier for the template (used in URLs)
        - type: `string`
      - `source` *required*: `object (2 properties) | object (5 properties)`
        - description: Where a template's source comes from, as the API shows it (showcase D10).
        - type: `object (2 properties) | object (5 properties)`
      - `tags` *required*: `array<string>`
        - description: Tags/categories for filtering
        - type: `array<string>`
  - `401`: Unauthorized
  - `404`: Template not found
  - `500`: Internal server error

### `GET /usage/ai-ocr-budget`

- operationId: `getAiOcrBudget`
- tags: `Usage`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The organization's AI+OCR budget and status
    - `application/json`:
      - type: `object (2 properties)`
      - `budget`: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `status`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `503`: A cost cannot be converted (missing FX rate)

### `PUT /usage/ai-ocr-budget`

- operationId: `setAiOcrBudget`
- tags: `Usage`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `currency` *required*: `string`
      - description: ISO-4217 alphabetic code, e.g. `EUR`. AI (USD) and OCR (EUR) supplier
      - type: `string`
    - `margin_bps`: `['integer', 'null']`
      - description: Margin over supplier cost in basis points (1500 = 15%). Platform
      - type: `['integer', 'null']`
    - `monthly_budget_minor` *required*: `integer`
      - description: Monthly budget in minor units (cents) of `currency`; `10000` is 100.00.
      - type: `integer`
- responses:
  - `200`: Budget set
    - `application/json`:
      - type: `object (6 properties)`
      - `currency` *required*: `string`
        - description: ISO-4217 alphabetic code, e.g. `EUR`.
        - type: `string`
      - `margin_bps` *required*: `integer`
        - description: Margin on supplier cost in basis points (1500 = 15%).
        - type: `integer`
      - `monthly_budget_minor` *required*: `integer`
        - description: Monthly budget in minor units (cents) of `currency`.
        - type: `integer`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `updated_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid budget
  - `401`: Unauthorized
  - `403`: Not an owner or admin, or margin_bps set by a non-platform-admin

### `DELETE /usage/ai-ocr-budget`

- operationId: `clearAiOcrBudget`
- tags: `Usage`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `204`: Budget cleared (or there was none)
  - `401`: Unauthorized
  - `403`: Not an owner or admin

### `GET /user/me`

- operationId: `get_current_user`
- summary: Returns the authenticated user's profile and effective role.
- tags: `Authentication`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved user information
    - `application/json`:
      - type: `object (8 properties)`
      - `account_reauthentication_path`: `['string', 'null']`
        - description: Where this browser session signs in again through its identity
        - type: `['string', 'null']`
      - `avatar_url` *required*: `string`
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `mfa_enabled` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role` *required*: `string`
        - description: User's role (e.g., "admin", "user", "demo")
        - type: `string`
      - `username` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /users`

- operationId: `list_users`
- summary: Every user on the installation, not the caller's organization.
- description: This is a **platform surface wearing a tenant-shaped path**. `/users` sits
beside org-scoped routes but is deliberately installation-wide: it backs the
console's platform-admin user management, where the whole point is seeing
accounts that belong to organizations the operator is not a member of.

It is safe because `UsersWrite` is granted only to `SuperAdmin` and
`PlatformAdmin` (see `conusai-auth-api`'s permission table) — never to
`Role::User` — so no tenant member reaches it. It is not an exception to
the rule in `docs/architecture/tenant-isolation.md`; it is the other case
that document names, a platform surface about the installation rather than
a tenant.

By that document's own taxonomy it belongs under `/admin/*`. It is not
there because the path is load-bearing for two shipped consumers — the
console's generated SDK and the MCP `users` tools — and moving it buys
naming consistency at the cost of breaking both, with no change to who can
call it.

**Do not "fix" this by adding an organization filter.** That would not
close a hole; it would break platform administration, which is the only
thing that can call it.
- tags: `Users`
- parameters:
  - `include_deleted` (query) *required*: `boolean`
- requestBody: _(none)_
- responses:
  - `200`: List all users with their roles
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `500`: Internal server error

### `POST /users`

- operationId: `create_user`
- summary: Create a new user with roles
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `password`: `['string', 'null']`
      - type: `['string', 'null']`
    - `roles` *required*: `array<string>`
      - type: `array<string>`
    - `username` *required*: `string`
      - type: `string`
- responses:
  - `201`: User created successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `roles` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `user` *required*: `object (10 properties)`
        - type: `object (10 properties)`
  - `400`: Invalid input
  - `403`: Not a user-management administrator, or the Community edition user cap is reached (no license installed)
  - `500`: Internal server error

### `PATCH /users/me`

- operationId: `update_self`
- summary: Update current user's information
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: User updated successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `roles` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `user` *required*: `object (10 properties)`
        - type: `object (10 properties)`
  - `400`: Invalid input, or an email field (urn:conusai:users:email-change-requires-verification)
  - `401`: Unauthorized
  - `500`: Internal server error

### `DELETE /users/me/mfa`

- operationId: `disable_mfa`
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `code` *required*: `string`
      - type: `string`
- responses:
  - `204`: MFA disabled
  - `400`: Invalid verification code
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /users/me/mfa/setup`

- operationId: `setup_mfa`
- tags: `Users`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: MFA setup data
    - `application/json`:
      - type: `object (3 properties)`
      - `qr_code` *required*: `string`
        - type: `string`
      - `recovery_codes` *required*: `array<string>`
        - type: `array<string>`
      - `secret_key` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /users/me/mfa/verify`

- operationId: `verify_and_enable_mfa`
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `code` *required*: `string`
      - type: `string`
- responses:
  - `204`: MFA verified and enabled
  - `400`: Invalid code
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /users/me/password`

- operationId: `change_password_self`
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `current_password` *required*: `string`
      - type: `string`
    - `mfa_code`: `['string', 'null']`
      - description: TOTP code (or recovery code). Required iff the user has MFA enabled.
      - type: `['string', 'null']`
    - `new_password` *required*: `string`
      - type: `string`
    - `revoke_other_sessions`: `boolean`
      - description: When true, every session OTHER than the one making this request is
      - type: `boolean`
- responses:
  - `204`: Password updated
  - `400`: Validation error (weak password, same as current, MFA missing)
  - `401`: Current password incorrect or MFA code invalid
  - `403`: Account has no password set (SSO/magic-link only)
  - `500`: Internal server error

### `PATCH /users/{user_id}`

- operationId: `update_user`
- summary: Update user information (admin only)
- tags: `Users`
- parameters:
  - `user_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: User updated successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `roles` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `user` *required*: `object (10 properties)`
        - type: `object (10 properties)`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `403`: Forbidden - Non-admin attempt
  - `404`: User not found
  - `500`: Internal server error

### `DELETE /users/{user_id}`

- operationId: `delete_user`
- summary: Delete a user
- tags: `Users`
- parameters:
  - `user_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: User deleted successfully
  - `401`: Unauthorized
  - `403`: Forbidden - Cannot delete yourself or non-admin attempt
  - `404`: User not found
  - `500`: Internal server error

### `POST /users/{user_id}/restore`

- operationId: `restore_user`
- tags: `Users`
- parameters:
  - `user_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: User restored successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `roles` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `user` *required*: `object (10 properties)`
        - type: `object (10 properties)`
  - `400`: User is not deleted
  - `401`: Unauthorized
  - `403`: Forbidden - Non-admin attempt
  - `404`: User not found
  - `500`: Internal server error

### `POST /users/{user_id}/roles`

- operationId: `assign_role`
- tags: `Users`
- parameters:
  - `user_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `role_type` *required*: `string`
      - type: `string`
    - `user_id` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Role assigned successfully
  - `400`: Invalid role type
  - `404`: User or role not found
  - `500`: Internal server error

### `DELETE /users/{user_id}/roles/{role_type}`

- operationId: `remove_role`
- tags: `Users`
- parameters:
  - `user_id` (path) *required*: `integer`
  - `role_type` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Role removed successfully
  - `400`: Invalid role type
  - `403`: Forbidden - Cannot modify own roles or non-admin attempt
  - `404`: User or role not found
  - `500`: Internal server error

### `GET /v1/admin/build-capacity`

- operationId: `get_build_capacity`
- summary: The capacity image builds have on this host: the shared builders'
slice ceiling, the per-organisation caps, and free space on Docker's
data root and the build scratch against the reserve.
- tags: `Deployments v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Build capacity on this host
    - `application/json`:
      - type: `object (8 properties)`
      - `build_scratch_free_bytes` *required*: `integer`
        - description: Free bytes on the build scratch: the deployment checkout or the
        - type: `integer`
      - `docker_root_free_bytes` *required*: `integer`
        - description: Free bytes on Docker's data root, where built images are imported.
        - type: `integer`
      - `parent_cpu_quota_percent`: `['integer', 'null']`
        - description: That slice's CPU quota in percent of one CPU (`200` is two CPUs);
        - type: `['integer', 'null']`
      - `parent_memory_max_bytes`: `['integer', 'null']`
        - description: That slice's memory ceiling in bytes; `null`: no ceiling (systemd
        - type: `['integer', 'null']`
      - `parent_slice` *required*: `string`
        - description: The systemd slice every organisation's builder slice nests under.
        - type: `string`
      - `per_org_cpu_limit_cores`: `['number', 'null']`
        - description: The CPU cap each organisation's builder gets, in cores; `null`:
        - type: `['number', 'null']`
      - `per_org_memory_limit_mb`: `['integer', 'null']`
        - description: The memory cap each organisation's builder gets, in MB; `null`:
        - type: `['integer', 'null']`
      - `reserve_bytes` *required*: `integer`
        - description: The free space a build needs on each of those filesystems; a build
        - type: `integer`
  - `401`: Unauthorized
  - `403`: SystemAdmin required
  - `503`: The settings, the build filesystems or the builders' slice could not be read

### `GET /v1/admin/modules`

- operationId: `admin_list_modules`
- summary: Every module installed on this instance, removed ones included.
- tags: `Modules`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Every module row of this instance, in name order
    - `application/json`:
      - type: `object (1 properties)`
      - `modules` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/admin/modules/releases`

- operationId: `apply_module_release`
- summary: Verify a signed release and make it the module's desired state; the
server pulls, migrates and starts it. A first install needs the operator
CLI's database provisioning.
- tags: `Modules`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `sbom` *required*: `string`
      - description: Exact UTF-8 `CycloneDX` SBOM authenticated by the signed SBOM digest.
      - type: `string`
    - `signature` *required*: `object`
      - type: `object`
    - `statement` *required*: `string`
      - description: The exact text of `release.json`; the signature covers these bytes.
      - type: `string`
- responses:
  - `202`: Recorded; the server applies it. `changed` is false when it already was the desired release
    - `application/json`:
      - type: `object (2 properties)`
      - `changed` *required*: `boolean`
        - description: `false` when the release was already the desired one (or the module
        - type: `boolean`
      - `module` *required*: `object (15 properties)`
        - description: One installed module of this instance.
        - type: `object (15 properties)`
  - `401`: No valid credential, or no browser session for the step-up
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: `provisioning-required`, `release-conflict` or `release-downgrade`
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: `urn:conusai:service:release-invalid` with its `reason`
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `428`: Fresh session verification required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/admin/modules/releases/verify`

- operationId: `verify_module_release`
- summary: Verify a signed release with the keys this instance trusts; nothing is
written.
- tags: `Modules`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `sbom` *required*: `string`
      - description: Exact UTF-8 `CycloneDX` SBOM authenticated by the signed SBOM digest.
      - type: `string`
    - `signature` *required*: `object`
      - type: `object`
    - `statement` *required*: `string`
      - description: The exact text of `release.json`; the signature covers these bytes.
      - type: `string`
- responses:
  - `200`: The release verifies
    - `application/json`:
      - type: `object (7 properties)`
      - `contract` *required*: `integer`
        - type: `integer`
      - `image` *required*: `string`
        - type: `string`
      - `kid` *required*: `string`
        - type: `string`
      - `migrations` *required*: `integer`
        - description: The number of migrations the release carries.
        - type: `integer`
      - `published_at` *required*: `string`
        - type: `string`
      - `service` *required*: `string`
        - type: `string`
      - `version` *required*: `string`
        - type: `string`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: `urn:conusai:service:release-invalid` with its `reason`
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/admin/modules/{name}/jobs/runs`

- operationId: `list_module_job_runs`
- summary: The newest runs of a module's jobs, of one organization or of all.
- tags: `Modules`
- parameters:
  - `name` (path) *required*: `string`
  - `org` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Runs, newest first
    - `application/json`:
      - type: `object (1 properties)`
      - `runs` *required*: `array<object (11 properties)>`
        - description: Newest first.
        - type: `array<object (11 properties)>`
  - `400`: `limit` outside 1 to 100, or `org` not a slug
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No such module installed, or no organization with this slug
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/admin/modules/{name}/jobs/{job}/runs`

- operationId: `request_module_job_run`
- summary: Make a declared job due now for one organization; the server's job worker
runs it within seconds.
- tags: `Modules`
- parameters:
  - `name` (path) *required*: `string`
  - `job` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `org` *required*: `string`
      - description: The organization's slug.
      - type: `string`
- responses:
  - `202`: The open run; the job worker dispatches it. `created` is false when a run was already open (a pending one is moved to now)
    - `application/json`:
      - type: `object (2 properties)`
      - `created` *required*: `boolean`
        - description: `false`: a run was already open; a pending one was moved to now.
        - type: `boolean`
      - `run` *required*: `object (11 properties)`
        - description: One run of a declared job for one organization.
        - type: `object (11 properties)`
  - `400`: `org` is not a slug
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No such module installed; `urn:conusai:service:job-unknown`; no organization with this slug; or `urn:conusai:service:not-enabled` for that organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry or the audit log could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/admin/modules/{name}/remove`

- operationId: `remove_module`
- summary: Remove a module from this instance. The server backs up and drops its
schema (it keeps the schema while no backup can be taken) and stops it.
- tags: `Modules`
- parameters:
  - `name` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `force`: `boolean`
      - description: Remove although organizations still enable it.
      - type: `boolean`
    - `reason`: `['string', 'null']`
      - description: Why; required with `force`, at most 500 characters.
      - type: `['string', 'null']`
- responses:
  - `202`: Recorded; the server removes it. `changed` is false when it already was removed
    - `application/json`:
      - type: `object (2 properties)`
      - `changed` *required*: `boolean`
        - description: `false` when the release was already the desired one (or the module
        - type: `boolean`
      - `module` *required*: `object (15 properties)`
        - description: One installed module of this instance.
        - type: `object (15 properties)`
  - `400`: `force` without a `reason`, or a reason longer than 500 characters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: No valid credential, or no browser session for the step-up
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No module with this name is installed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: `urn:conusai:service:still-enabled`, or the module is changing
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `428`: Fresh session verification required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/admin/ocr/engine`

- operationId: `engine_status`
- summary: The engine's status: enabled, ready, and the image tag this platform runs.
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The OCR engine's status
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - description: The engine container exists: a `SystemAdmin` enabled OCR and nobody disabled it.
        - type: `boolean`
      - `ready` *required*: `boolean`
        - description: The engine answers `/readyz` (its models are loaded).
        - type: `boolean`
      - `version` *required*: `string`
        - description: The engine image tag this platform runs.
        - type: `string`
  - `401`: Unauthorized
  - `403`: SystemAdmin required

### `POST /v1/admin/ocr/engine/disable`

- operationId: `disable_engine`
- summary: Disable OCR for the platform: reads answer 503 `not-enabled` at once, and the engine
container is removed (it keeps no state).
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The engine is disabled
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - description: The engine container exists: a `SystemAdmin` enabled OCR and nobody disabled it.
        - type: `boolean`
      - `ready` *required*: `boolean`
        - description: The engine answers `/readyz` (its models are loaded).
        - type: `boolean`
      - `version` *required*: `string`
        - description: The engine image tag this platform runs.
        - type: `string`
  - `401`: Unauthorized
  - `403`: SystemAdmin required
  - `503`: The engine container could not be removed

### `POST /v1/admin/ocr/engine/enable`

- operationId: `enable_engine`
- summary: Enable OCR for the platform: the engine container is created on its own internal network,
started, and serves `POST /v1/ocr` once its models are loaded. Answers when it is ready.
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The engine is enabled and ready
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - description: The engine container exists: a `SystemAdmin` enabled OCR and nobody disabled it.
        - type: `boolean`
      - `ready` *required*: `boolean`
        - description: The engine answers `/readyz` (its models are loaded).
        - type: `boolean`
      - `version` *required*: `string`
        - description: The engine image tag this platform runs.
        - type: `string`
  - `401`: Unauthorized
  - `403`: SystemAdmin required
  - `503`: The engine did not start or did not become ready

### `GET /v1/admin/platform/version`

- operationId: `get_platform_version`
- tags: `PlatformVersion`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Running platform version and channel status
    - `application/json`:
      - type: `object (8 properties)`
      - `build_time` *required*: `string`
        - description: When the binary was built, e.g. `2026-10-11 08:00:00 UTC`.
        - type: `string`
      - `bundle_version`: `['string', 'null']`
        - description: Vendor bundle version, when a bundle manifest is found.
        - type: `['string', 'null']`
      - `channel` *required*: `string`
        - description: Release channel the install tracks: `stable` or `beta` (derived from
        - type: `string`
      - `checked_at`: `['string', 'null']`
        - description: When the last successful channel check ran, RFC 3339. Null until the
        - type: `['string', 'null']`
      - `commit` *required*: `string`
        - description: Short commit hash the binary was built from.
        - type: `string`
      - `latest_available`: `['string', 'null']`
        - description: Newest release tag on the channel. Null until the first hourly check
        - type: `['string', 'null']`
      - `update_available` *required*: `boolean`
        - description: True when `latest_available` orders newer than `version`.
        - type: `boolean`
      - `version` *required*: `string`
        - description: Version tag of the running binary, e.g. `v0.1.0-beta.63`.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /v1/admin/releases/inventory`

- operationId: `release_inventory`
- summary: Local installation observations; never runs reconciliation or provider
mutations. Unknown fields of fact stay unknown and do not establish grants.
- tags: `Release inventory`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Read-only installed byte and registry observations
    - `application/json`:
      - type: `object (15 properties)`
      - `accepted_release_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `binary_build_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `binary_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `components` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
      - `distribution`: `['string', 'null']`
        - type: `['string', 'null']`
      - `observed_at` *required*: `string`
        - type: `string`
      - `packages` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `reason_codes` *required*: `array<string>`
        - type: `array<string>`
      - `schema_version` *required*: `integer`
        - type: `integer`
      - `source_commit`: `['string', 'null']`
        - type: `['string', 'null']`
      - `templates` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `vendor_bundle_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `vendor_manifest_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `vendor_source_commit`: `['string', 'null']`
        - type: `['string', 'null']`
      - `vendor_version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: SystemAdmin required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Inventory observations unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/blob/downloads`

- operationId: `create_download`
- summary: Direct native download URL compatibility endpoint. Native clients use the
authenticated managed Blob stream; direct-storage capabilities are refused.
- tags: `Blob`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `expires_in_seconds`: `['integer', 'null']`
      - description: Clamped to 900s (15 min) regardless of what is asked for.
      - type: `['integer', 'null']`
    - `pathname` *required*: `string`
      - type: `string`
    - `project_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: A presigned download URL was created
    - `application/json`:
      - type: `object (2 properties)`
      - `downloadUrl` *required*: `string`
        - type: `string`
      - `expiresAt` *required*: `string`
        - type: `string`
  - `400`: Invalid request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `501`: Use authenticated managed Blob streaming
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/blob/uploads`

- operationId: `create_upload`
- summary: Begin a presigned upload
- tags: `Blob`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `content_type` *required*: `string`
      - type: `string`
    - `pathname` *required*: `string`
      - type: `string`
    - `project_id`: `['integer', 'null']`
      - description: Project ID (required for API key/session authentication, optional
      - type: `['integer', 'null']`
    - `size_bytes` *required*: `integer`
      - type: `integer`
- responses:
  - `201`: A presigned single or multipart upload was created
    - `application/json`:
      - type: `object (5 properties)`
      - `expiresAt` *required*: `string`
        - type: `string`
      - `pathname` *required*: `string`
        - type: `string`
      - `sizeBytes` *required*: `integer`
        - type: `integer`
      - `upload` *required*: `object (2 properties) | object (4 properties)`
        - description: What `request_upload` hands back: either one presigned PUT, or a
        - type: `object (2 properties) | object (4 properties)`
      - `uploadId` *required*: `string`
        - type: `string`
  - `400`: Invalid request, or the size/MIME policy was violated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/blob/uploads/{id}/complete`

- operationId: `complete_upload`
- summary: Finalize a presigned upload
- tags: `Blob`
- parameters:
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `parts`: `['array', 'null']`
      - description: Required, and non-empty, iff the upload was multipart.
      - type: `['array', 'null']`
    - `project_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: The upload was validated, moved to its final key and registered
    - `application/json`:
      - type: `object (5 properties)`
      - `contentType` *required*: `string`
        - type: `string`
      - `pathname` *required*: `string`
        - type: `string`
      - `sha256Digest` *required*: `string`
        - type: `string`
      - `size` *required*: `integer`
        - type: `integer`
      - `uploadedAt` *required*: `string`
        - type: `string`
  - `400`: Invalid request, or the size/MIME/quota policy was violated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Upload or project not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `410`: The upload expired before it was completed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /v1/blob/uploads/{id}/content`

- operationId: `upload_content`
- summary: Send the bytes of an upload
- description: The request body is the raw object (single upload) or one part (multipart
upload). `Content-Length` is required and must equal the expected size.
- tags: `Blob`
- parameters:
  - `id` (path) *required*: `string`
  - `project_id` (query): `['integer', 'null']`
  - `part` (query): `['integer', 'null']`
- requestBody:
  - `application/octet-stream`:
    - type: `array<integer>`
- responses:
  - `200`: The bytes were staged
    - `application/json`:
      - type: `object (2 properties)`
      - `etag` *required*: `string`
        - description: The entity tag to report back to `/complete` for a multipart upload.
        - type: `string`
      - `partNumber` *required*: `integer`
        - description: The part stored (a single upload is part 1).
        - type: `integer`
  - `400`: Missing or wrong Content-Length, a body of another length, or a wrong part number
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing required Blob permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Upload or project not found, or the upload is no longer pending
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `410`: The upload expired before its bytes arrived
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/budget/ai-ocr`

- operationId: `getDeploymentAiOcrBudget`
- tags: `AI Gateway Budget`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The token's own organization AI+OCR budget status
    - `application/json`:
      - type: `object (6 properties)`
      - `blocked` *required*: `boolean`
        - description: Whether the configured AI+OCR budget is exhausted.
        - type: `boolean`
      - `currency`: `['string', 'null']`
        - description: The configured budget's ISO-4217 currency, or `null` with no budget.
        - type: `['string', 'null']`
      - `limit`: `['integer', 'null']`
        - description: Monthly budget in minor units, or `null` with no configured budget.
        - type: `['integer', 'null']`
      - `period_end` *required*: `string`
        - description: Exclusive end of the current UTC calendar-month cycle.
        - type: `string`
      - `spent`: `['integer', 'null']`
        - description: Current-cycle AI+OCR spend in budget minor units, or `null` with no
        - type: `['integer', 'null']`
      - `warning_level`: `['integer', 'null']`
        - description: Highest reached threshold (50, 80, or 100 percent); `null` below 50
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Not a deployment token, or neither ai:execute nor ocr:use is granted
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The token's project or organization was not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Budget status could not be read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: A cost cannot be converted (missing FX rate)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/identity/links/{link_id}/admissions`

- operationId: `request_identity_admission`
- summary: Admit an address to this link with the app-access role `user`.
- tags: `Identity admissions v1`
- parameters:
  - `link_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email` *required*: `string`
      - description: The address to admit. Used for delivery only; never stored or logged.
      - type: `string`
    - `invitation_id` *required*: `string`
      - description: The app's own invitation id (1–128 of `A–Z a–z 0–9 . _ : -`). A
      - type: `string`
- responses:
  - `202`: Accepted for every address; access follows the person's verification
    - `application/json`:
      - type: `object (2 properties)`
      - `admission_id` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - description: `pending` only: access follows the person's verification.
        - type: `string`
  - `401`: Missing or invalid admission credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The credential belongs to another link
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Malformed body, unknown field (a role included) or invitation id reused for another address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: The link's admission limit (30 per hour, 300 per day) is reached; see Retry-After
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/identity/links/{link_id}/admissions/tickets`

- operationId: `request_identity_admission_ticket`
- summary: A sign-up ticket of an admission of this link: the address is admitted as
by the admission endpoint, then the identity service is asked for it.
- tags: `Identity admissions v1`
- parameters:
  - `link_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email` *required*: `string`
      - description: The address to admit. Used for delivery only; never stored or logged.
      - type: `string`
    - `invitation_id` *required*: `string`
      - description: The app's own invitation id (1–128 of `A–Z a–z 0–9 . _ : -`). A
      - type: `string`
- responses:
  - `200`: A ten-minute, single-use sign-up ticket; the same for every address
    - `application/json`:
      - type: `object (2 properties)`
      - `expires_in` *required*: `integer`
        - description: Seconds the ticket stays good (600).
        - type: `integer`
      - `ticket` *required*: `string`
        - type: `string`
  - `401`: Missing or invalid admission credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The credential belongs to another link
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The link's identity service issues no sign-up tickets
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Malformed body, unknown field or invitation id reused for another address
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: The link's admission limit is reached; see Retry-After
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The identity service could not be reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/identity/people/erase`

- operationId: `erase_identity_person_for_app`
- summary: Erase the app's own signed-in person, with the link's admission credential.
A repeat is the same `202`, so the app's resumable deletion can retry.
- tags: `Identity admissions v1`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `subject` *required*: `string`
      - description: The app's own signed-in subject.
      - type: `string`
- responses:
  - `202`: Accepted; `applied` once the provider confirmed. The platform finishes it
    - `application/json`:
      - type: `object (2 properties)`
      - `operation_id` *required*: `string`
        - description: Follow it at `GET …/identity/operations`. Never names the subject.
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Missing or invalid admission credential, or a link that no longer admits
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: A subject this link does not know
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The provider cannot do this (identity-user-deletion-unsupported), or another link of the service still lets this account in (identity-person-on-other-links): an operator erases it
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Malformed body or subject, or an unknown field
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The identity provider is unavailable; retry
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/identity/people/export`

- operationId: `export_identity_person_for_app`
- summary: What the provider holds about the app's own signed-in person, with the
link's admission credential: the account, and only this link's grants and
admissions. The app includes it in its own export; the answer is `no-store`.
- tags: `Identity admissions v1`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `subject` *required*: `string`
      - description: The app's own signed-in subject.
      - type: `string`
- responses:
  - `200`: The person's account data
    - `application/json`:
      - type: `object (9 properties)`
      - `admissions` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `created_at` *required*: `string`
        - description: RFC 3339.
        - type: `string`
      - `email` *required*: `string`
        - type: `string`
      - `email_verified` *required*: `boolean`
        - type: `boolean`
      - `grants` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `name` *required*: `string`
        - type: `string`
      - `passkeys` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sessions` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `subject` *required*: `string`
        - description: Opaque provider subject.
        - type: `string`
  - `401`: Missing or invalid admission credential, or a link that no longer admits
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: A subject this link does not know
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The provider cannot do this (identity-user-deletion-unsupported)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Malformed body or subject, or an unknown field
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The identity provider is unavailable; retry
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/live/metrics`

- operationId: `get_live_metrics`
- summary: The live kernel's process metrics in the Prometheus text format.
- tags: `Live`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Prometheus text exposition 0.0.4: live_streams_open, live_changes_delivered_total, live_resync_total{reason}, live_xmin_lag_seconds, live_reader_batch_seconds, live_notify_wakeups_total
    - `text/plain`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Not a platform operator

### `GET /v1/monitoring/config`

- operationId: `getMonitoringConfig`
- summary: The node-alarm threshold configuration.
- tags: `Monitoring`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Threshold configuration
    - `application/json`:
      - type: `object (10 properties)`
      - `cpu_high_for_secs` *required*: `integer`
        - type: `integer`
      - `cpu_high_pct` *required*: `number`
        - type: `number`
      - `disk_full_for_secs` *required*: `integer`
        - type: `integer`
      - `disk_full_pct` *required*: `number`
        - type: `number`
      - `mem_high_for_secs` *required*: `integer`
        - type: `integer`
      - `mem_high_pct` *required*: `number`
        - type: `number`
      - `metrics_retention_days` *required*: `integer`
        - type: `integer`
      - `node_offline_after_secs` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `wg_handshake_stale_secs` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Requires monitoring_infra:read (operator only)
  - `500`: Internal server error

### `PUT /v1/monitoring/config`

- operationId: `updateMonitoringConfig`
- summary: Update the node-alarm thresholds (partial update).
- tags: `Monitoring`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `cpu_high_for_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `cpu_high_pct`: `['number', 'null']`
      - type: `['number', 'null']`
    - `disk_full_for_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `disk_full_pct`: `['number', 'null']`
      - type: `['number', 'null']`
    - `mem_high_for_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `mem_high_pct`: `['number', 'null']`
      - type: `['number', 'null']`
    - `metrics_retention_days`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `node_offline_after_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `wg_handshake_stale_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: Updated configuration
    - `application/json`:
      - type: `object (10 properties)`
      - `cpu_high_for_secs` *required*: `integer`
        - type: `integer`
      - `cpu_high_pct` *required*: `number`
        - type: `number`
      - `disk_full_for_secs` *required*: `integer`
        - type: `integer`
      - `disk_full_pct` *required*: `number`
        - type: `number`
      - `mem_high_for_secs` *required*: `integer`
        - type: `integer`
      - `mem_high_pct` *required*: `number`
        - type: `number`
      - `metrics_retention_days` *required*: `integer`
        - type: `integer`
      - `node_offline_after_secs` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `wg_handshake_stale_secs` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Requires monitoring:write (operator only)
  - `500`: Internal server error

### `GET /v1/monitoring/nodes`

- operationId: `listMonitoredNodes`
- summary: List every node with its latest metric summary (operator fleet table).
- tags: `Monitoring`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Nodes with latest metric summary
    - `application/json`:
      - type: `object (1 properties)`
      - `nodes` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
  - `401`: Unauthorized
  - `403`: Requires monitoring_infra:read (operator only)
  - `500`: Internal server error

### `GET /v1/monitoring/nodes/{node_id}/alarms`

- operationId: `listNodeAlarms`
- summary: Active (unresolved) alarms raised against one node.
- tags: `Monitoring`
- parameters:
  - `node_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Active node alarms
    - `application/json`:
      - type: `object (2 properties)`
      - `alarms` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `node_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Requires monitoring_infra:read (operator only)
  - `500`: Internal server error

### `GET /v1/monitoring/nodes/{node_id}/metrics`

- operationId: `getNodeMetricSeries`
- summary: 5-minute rollup series for one node metric, from the CAGG (never raw).
- tags: `Monitoring`
- parameters:
  - `node_id` (path) *required*: `integer`
  - `metric` (query) *required*: `string`
  - `hours` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: 5m rollup series
    - `application/json`:
      - type: `object (3 properties)`
      - `metric` *required*: `string`
        - type: `string`
      - `node_id` *required*: `integer`
        - type: `integer`
      - `points` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `400`: Invalid query
  - `401`: Unauthorized
  - `403`: Requires monitoring_infra:read (operator only)
  - `500`: Internal server error

### `POST /v1/ocr`

- operationId: `read_with_token`
- summary: Read a document as the app whose deployment token calls: text, lines, words and boxes as
`conusai.ocr.document/v1`. At most 10 pages; a longer document is refused with 413 and belongs
on `/v1/ocr/jobs`. Every page returned is metered (`ocr_pages`) to the token's project; this is
the route `@conusai-sdk/ocr` calls with `CONUSAI_API_TOKEN`.
- tags: `OCR v1`
- parameters: _(none)_
- requestBody:
  - `multipart/form-data`:
    - type: `object (5 properties)`
    - `file`: `['string', 'null']`
      - description: The document: PDF, PNG, JPEG, TIFF, WebP or BMP, at most 20 MB. Send this or `object`.
      - type: `['string', 'null']`
    - `object`: `['string', 'null']`
      - description: Pathname of a document already in this project's Blob store (e.g. `invoices/42.pdf`),
      - type: `['string', 'null']`
    - `pages`: `['string', 'null']`
      - description: 1-based page ranges such as `1-3,5`; every page when absent.
      - type: `['string', 'null']`
    - `tables`: `['boolean', 'null']`
      - description: `true` adds each page's line-item tables (cells, rows, columns, HTML); part of `read`'s price.
      - type: `['boolean', 'null']`
    - `text_layer`: `['string', 'null']`
      - description: `auto` (default) uses a PDF page's text layer when it has one; `ignore` always OCRs.
      - type: `['string', 'null']`
- responses:
  - `200`: The document read, conusai.ocr.document/v1
    - `application/json`:
      - type: `any`
  - `400`: Malformed request
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: The token's project, or the object it names, was not found
  - `413`: Body, page or page-count limit exceeded
  - `415`: Not a document the engine reads
  - `422`: Invalid text_layer or page range, or an unreadable PDF
  - `500`: Internal error
  - `503`: OCR is not enabled on this platform, or the engine is unavailable

### `GET /v1/ocr/engine`

- operationId: `status`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The active organization's dedicated OCR engine
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `ready` *required*: `boolean`
        - type: `boolean`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Organization owner or admin required

### `POST /v1/ocr/engine/disable`

- operationId: `disable`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The dedicated engine is disabled
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `ready` *required*: `boolean`
        - type: `boolean`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Organization owner or admin required
  - `503`: The dedicated engine could not be disabled

### `POST /v1/ocr/engine/enable`

- operationId: `enable`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The dedicated engine is enabled and ready
    - `application/json`:
      - type: `object (3 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `ready` *required*: `boolean`
        - type: `boolean`
      - `version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Organization owner or admin required
  - `503`: The dedicated engine could not be enabled

### `POST /v1/ocr/extract`

- operationId: `extract_with_token`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody:
  - `multipart/form-data`:
    - type: `object (8 properties)`
    - `file`: `['string', 'null']`
      - type: `['string', 'null']`
    - `instructions`: `['string', 'null']`
      - description: Extra instructions narrowing what to look for.
      - type: `['string', 'null']`
    - `model`: `['string', 'null']`
      - description: Optional model id, resolved through the same gateway allowlist as stored-job extraction.
      - type: `['string', 'null']`
    - `object`: `['string', 'null']`
      - type: `['string', 'null']`
    - `pages`: `['string', 'null']`
      - type: `['string', 'null']`
    - `preset`: `['string', 'null']`
      - description: A published preset name, such as `invoice`. Send this or `schema`, not both.
      - type: `['string', 'null']`
    - `schema`: `['string', 'null']`
      - description: A JSON Schema of the shape to extract. Send this or `preset`, not both.
      - type: `['string', 'null']`
    - `text_layer`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: The extraction: grounded data and the evidence for every value
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, unknown preset, or an unusable schema
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: The token's project, or the object it names, was not found
  - `413`: Body, page or page-count limit exceeded
  - `415`: Not a document the engine reads
  - `422`: Unreadable document, or no valid extraction in two attempts
  - `500`: Internal error
  - `502`: The extraction model could not be reached
  - `503`: OCR is not enabled, the engine is unavailable, or no model is configured

### `POST /v1/ocr/jobs`

- operationId: `submit`
- summary: Submit a document for asynchronous reading: the same form as `/v1/ocr`, for documents over
its 10-page limit. Returns 202 with `Location: /v1/ocr/jobs/{id}` and `Retry-After`; poll
`GET` on `Location` for status and `.../result` once it `succeeded`. `Idempotency-Key` makes
a retried submission of the same request answer the same job instead of reading it twice
(AWS-style: the same key with a different body is a 409).
- tags: `OCR v1`
- parameters: _(none)_
- requestBody:
  - `multipart/form-data`:
    - type: `object (5 properties)`
    - `file`: `['string', 'null']`
      - description: The document: PDF, PNG, JPEG, TIFF, WebP or BMP, at most 20 MB. Send this or `object`.
      - type: `['string', 'null']`
    - `object`: `['string', 'null']`
      - description: Pathname of a document already in this project's Blob store (e.g. `invoices/42.pdf`),
      - type: `['string', 'null']`
    - `pages`: `['string', 'null']`
      - description: 1-based page ranges such as `1-3,5`; every page when absent.
      - type: `['string', 'null']`
    - `tables`: `['boolean', 'null']`
      - description: `true` adds each page's line-item tables (cells, rows, columns, HTML); part of `read`'s price.
      - type: `['boolean', 'null']`
    - `text_layer`: `['string', 'null']`
      - description: `auto` (default) uses a PDF page's text layer when it has one; `ignore` always OCRs.
      - type: `['string', 'null']`
- responses:
  - `202`: Accepted; poll Location for status
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - description: Only set once `status` is `failed`.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `pages`: `['integer', 'null']`
        - description: The real page count once the engine has read the document; until then, the submitted
        - type: `['integer', 'null']`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: One of `queued`, `running`, `succeeded` or `failed`. The internal `pending` upload
        - type: `string`
  - `400`: Malformed request
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: The token's project, or the object it names, was not found
  - `409`: Idempotency-Key reused with a different request
  - `413`: Body limit exceeded
  - `422`: Invalid text_layer or page range
  - `500`: Internal error
  - `503`: OCR or Blob storage is not available on this platform, or this organization's job limits could not be read; retry

### `GET /v1/ocr/jobs/{id}`

- operationId: `get_job`
- summary: A job's status, scoped to the deployment token's own project: another project's job id
answers 404, the same as a missing one (the 404 rule `/v1/ocr`'s object lookup also keeps).
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The job's current status
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - description: Only set once `status` is `failed`.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `pages`: `['integer', 'null']`
        - description: The real page count once the engine has read the document; until then, the submitted
        - type: `['integer', 'null']`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: One of `queued`, `running`, `succeeded` or `failed`. The internal `pending` upload
        - type: `string`
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: No job with this id in the token's own project
  - `500`: Internal error

### `GET /v1/ocr/jobs/{id}/pages/{n}.png`

- operationId: `get_page`
- summary: One page of a succeeded job's document as `image/png`: `n` is the 1-based page number in the
source document, the number in a block id (`p3-b2` is on `pages/3.png`). Rendered by the
engine on the first request and answered from a content-addressed cache after that. 404 for
a job that does not exist, is another project's, or has not succeeded; 422 for a spreadsheet
(no page image), a dpi out of bounds, or a page past the end.
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
  - `n` (path) *required*: `integer`
  - `dpi` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: The page as a PNG image
    - `image/png`:
      - type: `string`
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: No succeeded job with this id in the token's own project, or its input has expired
  - `422`: dpi out of bounds, page out of range, or the input has no pages to draw
  - `500`: Internal error
  - `503`: OCR or Blob storage is not available on this platform

### `GET /v1/ocr/jobs/{id}/result`

- operationId: `get_result`
- summary: A succeeded job's document, `conusai.ocr.document/v1`, as `/v1/ocr` returns it. 404 for a job
that does not exist, has not finished, or failed — the status is at `GET .../jobs/{id}`.
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: conusai.ocr.document/v1
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use
  - `404`: No succeeded job with this id in the token's own project
  - `500`: Internal error
  - `503`: Blob storage unavailable

### `GET /v1/ocr/jobs/{id}/source`

- operationId: `get_source`
- summary: The admitted job's original bytes, never a public/signed URL. Served as an attachment with
no MIME sniffing; application servers must authorize their own document before proxying.
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Original bytes; private attachment
    - `application/octet-stream`:
      - type: `string`
  - `403`: Requires an ocr:use deployment token
  - `404`: Job absent, expired, unfinished or in another project
  - `503`: Blob storage unavailable

### `POST /v1/ocr/jobs/{job_id}/extract`

- operationId: `extractFromOcrJob`
- tags: `OCR v1`
- parameters:
  - `job_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `idempotency_key`: `['string', 'null']`
      - description: Durable idempotency key; a repeat returns the same run's answer without another model call.
      - type: `['string', 'null']`
    - `instructions`: `['string', 'null']`
      - type: `['string', 'null']`
    - `model`: `['string', 'null']`
      - description: Optional model name, authorized by the AI service's existing allowlist.
      - type: `['string', 'null']`
    - `pages`: `['string', 'null']`
      - description: 1-based source pages, for example 1-3,5. All stored pages when omitted.
      - type: `['string', 'null']`
    - `preset`: `['string', 'null']`
      - description: Published extraction preset, such as invoice.
      - type: `['string', 'null']`
    - `schema`: `any`
      - description: JSON Schema of the shape to extract. Exactly one of schema and preset is required.
      - type: `any`
- responses:
  - `200`: Grounded extraction plus job_id and page_spec
    - `application/json`:
      - type: `any`
  - `400`: Malformed request or schema/preset selection
  - `402`: AI+OCR budget exhausted; no window was metered
  - `403`: Requires an ocr:use deployment token
  - `404`: Job absent, unfinished or in another project
  - `409`: Idempotency conflict or concurrent run
  - `410`: Stored OCR result or source expired; re-submit the document
  - `413`: More than ten pages; use POST /v1/ocr/jobs/{job_id}/runs
  - `502`: The requested or configured model refused the call
  - `503`: Blob, rendering or model unavailable

### `POST /v1/ocr/jobs/{job_id}/items`

- operationId: `submitOcrItems`
- tags: `OCR v1`
- parameters:
  - `job_id` (path) *required*: `integer`
  - `Idempotency-Key` (header): `['string', 'null']`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `idempotency_key`: `['string', 'null']`
      - description: Durable idempotency key; a repeat returns the same run. The `Idempotency-Key` header
      - type: `['string', 'null']`
    - `keep`: `array<string>`
      - description: Item classes to return; every class when empty.
      - type: `array<string>`
    - `link`: `['array', 'null']`
      - description: Profiles to link the items to, such as `spec_sections`; the profile's own `link` when omitted.
      - type: `['array', 'null']`
    - `mode`: `string`
      - type: `string`
    - `pages`: `['string', 'null']`
      - description: 1-based source pages, for example `1-3,5`; the document map's candidates when omitted.
      - type: `['string', 'null']`
    - `profile` *required*: `string`
      - description: Profile id, such as `bill_of_quantities`.
      - type: `string`
    - `profile_version`: `['integer', 'null']`
      - description: Profile version; the latest when omitted.
      - type: `['integer', 'null']`
- responses:
  - `202`: Items run accepted; poll Location, then read GET /v1/ocr/runs/{run_id}/result (conusai.documents.items/v1)
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `job_id` *required*: `integer`
        - type: `integer`
      - `pages_done` *required*: `integer`
        - type: `integer`
      - `pages_total` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `task` *required*: `string`
        - type: `string`
      - `windows` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `400`: Unknown profile or version, or malformed request
  - `403`: Requires an ocr:use deployment token
  - `404`: Job absent, unfinished or in another project
  - `409`: Idempotency key reused with another request
  - `410`: Stored OCR result expired
  - `422`: The profile's model region cannot be served (EU fails closed)
  - `501`: The items pipeline is not available on this server

### `GET /v1/ocr/jobs/{job_id}/map`

- operationId: `getOcrJobMap`
- tags: `OCR v1`
- parameters:
  - `job_id` (path) *required*: `integer`
  - `profile` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: The document map, conusai.documents.map/v1
    - `application/json`:
      - type: `object (9 properties)`
      - `contents` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `file_sha256` *required*: `string`
        - type: `string`
      - `headings` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `job_id` *required*: `integer`
        - type: `integer`
      - `page_count` *required*: `integer`
        - type: `integer`
      - `pages` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `pipeline_revision` *required*: `string`
        - type: `string`
      - `profile` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `schema_version` *required*: `string`
        - description: Always `conusai.documents.map/v1`.
        - type: `string`
  - `400`: Unknown profile
  - `401`: No valid credential: the request carries no session or token, or it is expired or revoked
  - `403`: Requires an ocr:use deployment token
  - `404`: Job absent, unfinished, failed or in another project
  - `410`: Stored OCR result expired; re-submit the document
  - `503`: Blob storage is not configured on this platform, or the OCR custody authority is unavailable

### `POST /v1/ocr/jobs/{job_id}/runs`

- operationId: `submitOcrRun`
- tags: `OCR v1`
- parameters:
  - `job_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `task` *required*: `string`
      - description: Task to execute: `extract` or `tables`; the remaining fields are that task's request.
      - type: `string`
- responses:
  - `202`: Run accepted; poll Location
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `job_id` *required*: `integer`
        - type: `integer`
      - `pages_done` *required*: `integer`
        - type: `integer`
      - `pages_total` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `task` *required*: `string`
        - type: `string`
      - `windows` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `400`: Unknown task or malformed task request
  - `403`: Requires an ocr:use deployment token
  - `404`: Job absent, unfinished or in another project
  - `409`: Idempotency key reused with another request
  - `410`: Stored OCR result expired

### `POST /v1/ocr/jobs/{job_id}/tables`

- operationId: `readTablesFromOcrJob`
- tags: `OCR v1`
- parameters:
  - `job_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `allow_model_mapping`: `boolean`
      - type: `boolean`
    - `columns` *required*: `array<object (8 properties)>`
      - type: `array<object (8 properties)>`
    - `idempotency_key`: `['string', 'null']`
      - type: `['string', 'null']`
    - `min_rows`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `model`: `['string', 'null']`
      - type: `['string', 'null']`
    - `number_format`: `object (3 properties) | null`
      - type: `object (3 properties) | null`
    - `pages`: `['string', 'null']`
      - type: `['string', 'null']`
    - `summary_aliases`: `array<string>`
      - type: `array<string>`
    - `table_template_ids`: `array<integer>`
      - type: `array<integer>`
- responses:
  - `200`: Reconstructed tables, conusai.ocr.tables/v1
    - `application/json`:
      - type: `any`
  - `400`: Malformed column definitions or page selection
  - `402`: AI+OCR budget exhausted; no window was metered
  - `403`: Requires an ocr:use deployment token or the model is not allowed
  - `404`: Job absent, unfinished or in another project
  - `409`: Idempotency conflict or concurrent run
  - `410`: Stored OCR result expired; re-submit the document
  - `413`: More than ten pages; use POST /v1/ocr/jobs/{job_id}/runs
  - `422`: Unreadable geometry or invalid model mapping
  - `502`: The header mapping model could not be reached
  - `503`: Blob or model unavailable

### `GET /v1/ocr/profiles`

- operationId: `listOcrProfiles`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The latest version of every document profile
    - `application/json`:
      - type: `object (1 properties)`
      - `profiles` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `403`: Requires an ocr:use deployment token

### `GET /v1/ocr/profiles/{profile_id}`

- operationId: `getOcrProfile`
- tags: `OCR v1`
- parameters:
  - `profile_id` (path) *required*: `string`
  - `version` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: The profile, conusai.documents.profile/v1
    - `application/json`:
      - type: `object (15 properties)`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `eval` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `id` *required*: `string`
        - type: `string`
      - `item_schema` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `layout` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `link` *required*: `array<string>`
        - type: `array<string>`
      - `locate` *required*: `object (3 properties)`
        - type: `object (3 properties)`
      - `models` *required*: `object`
        - description: Model policy per stage (`extract`, `escalate`, `link`, …).
        - type: `object`
      - `normalise` *required*: `object (1 properties)`
        - type: `object (1 properties)`
      - `review` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `schema_version` *required*: `string`
        - description: Always `conusai.documents.profile/v1`.
        - type: `string`
      - `sections` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `title` *required*: `string`
        - type: `string`
      - `validate` *required*: `object (1 properties)`
        - type: `object (1 properties)`
      - `version` *required*: `integer`
        - type: `integer`
  - `403`: Requires an ocr:use deployment token
  - `404`: No profile of that id and version

### `GET /v1/ocr/runs`

- operationId: `listOcrRuns`
- tags: `OCR v1`
- parameters:
  - `job_id` (query): `['integer', 'null']`
  - `task` (query): `['string', 'null']`
  - `cursor` (query): `['integer', 'null']`
  - `limit` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Runs newest first, with an id cursor
    - `application/json`:
      - type: `object (2 properties)`
      - `next_cursor`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `runs` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
  - `403`: Requires an ocr:use deployment token

### `GET /v1/ocr/runs/{run_id}`

- operationId: `getOcrRun`
- tags: `OCR v1`
- parameters:
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Run status and page windows
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `job_id` *required*: `integer`
        - type: `integer`
      - `pages_done` *required*: `integer`
        - type: `integer`
      - `pages_total` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `task` *required*: `string`
        - type: `string`
      - `windows` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `403`: Requires an ocr:use deployment token
  - `404`: Run absent or in another project
  - `410`: Run expired

### `POST /v1/ocr/runs/{run_id}/cancel`

- operationId: `cancelOcrRun`
- tags: `OCR v1`
- parameters:
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Cancellation accepted or run already terminal
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `job_id` *required*: `integer`
        - type: `integer`
      - `pages_done` *required*: `integer`
        - type: `integer`
      - `pages_total` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `task` *required*: `string`
        - type: `string`
      - `windows` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
  - `403`: Requires an ocr:use deployment token
  - `404`: Run absent or in another project
  - `410`: Run expired

### `POST /v1/ocr/runs/{run_id}/items/feedback`

- operationId: `postOcrItemsFeedback`
- tags: `OCR v1`
- parameters:
  - `run_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `decisions` *required*: `array<object (5 properties)>`
      - type: `array<object (5 properties)>`
- responses:
  - `202`: Decisions recorded as org-scoped feedback
    - `application/json`:
      - type: `object (2 properties)`
      - `accepted` *required*: `integer`
        - type: `integer`
      - `run_id` *required*: `integer`
        - type: `integer`
  - `400`: Unknown item id or malformed decision
  - `403`: Requires an ocr:use deployment token
  - `404`: Run absent, not an items run, or in another project
  - `501`: The items pipeline is not available on this server

### `GET /v1/ocr/runs/{run_id}/result`

- operationId: `getOcrRunResult`
- tags: `OCR v1`
- parameters:
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Merged task result; an items run's is conusai.documents.items/v1 (DocumentItems)
    - `application/json`:
      - type: `any`
  - `403`: Requires an ocr:use deployment token
  - `404`: Run absent or in another project
  - `409`: Run not finished
  - `410`: Run expired

### `GET /v1/ocr/status`

- operationId: `status_with_token`
- summary: Whether the token's organization can read right now, for an app that wants to pause its own
queue while its selected engine restarts. Jobs need no such pause: they wait for the engine
themselves. The per-organization probe is cached for two seconds.
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The service's readiness
    - `application/json`:
      - type: `object (2 properties)`
      - `ready` *required*: `boolean`
        - description: The engine is attached and its models are loaded.
        - type: `boolean`
      - `retry_after_seconds`: `['integer', 'null']`
        - description: Seconds to wait before asking again while the engine restarts; `null` when ready, or when
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Not a deployment token, or the token lacks ocr:use

### `GET /v1/ocr/table-templates`

- operationId: `listOcrTableTemplates`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Visible table templates
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
  - `403`: Organization membership or ocr:use required

### `POST /v1/ocr/table-templates`

- operationId: `createOcrTableTemplate`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `column_keys` *required*: `object`
      - description: Column index (a decimal string, from 0) to the key that column fills.
      - type: `object`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `project_scoped`: `boolean`
      - type: `boolean`
    - `row_rules`: `any`
      - type: `any`
    - `source` *required*: `object (3 properties)`
      - type: `object (3 properties)`
- responses:
  - `201`: Template created
    - `application/json`:
      - type: `object (16 properties)`
      - `column_bounds` *required*: `array<array<number>>`
        - type: `array<array<number>>`
      - `column_count` *required*: `integer`
        - type: `integer`
      - `column_keys` *required*: `array<['string', 'null']>`
        - type: `array<['string', 'null']>`
      - `confirmed_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `header_fingerprint` *required*: `string`
        - type: `string`
      - `header_texts` *required*: `array<string>`
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `row_rules` *required*: `any`
        - type: `any`
      - `source_job_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid source, keys or rules
  - `403`: ocr:use required or plan limit reached
  - `404`: Source job not found
  - `410`: Source OCR result expired

### `GET /v1/ocr/table-templates/match`

- operationId: `matchOcrTableTemplates`
- tags: `OCR v1`
- parameters:
  - `job_id` (query) *required*: `integer`
  - `pages` (query): `['string', 'null']`
  - `table_index` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Matching templates and conflict flag
    - `application/json`:
      - type: `object (2 properties)`
      - `candidates` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `conflict` *required*: `boolean`
        - type: `boolean`
  - `404`: Source job not found
  - `410`: Source OCR result expired

### `GET /v1/ocr/table-templates/{template_id}`

- operationId: `getOcrTableTemplate`
- tags: `OCR v1`
- parameters:
  - `template_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Table template
    - `application/json`:
      - type: `object (16 properties)`
      - `column_bounds` *required*: `array<array<number>>`
        - type: `array<array<number>>`
      - `column_count` *required*: `integer`
        - type: `integer`
      - `column_keys` *required*: `array<['string', 'null']>`
        - type: `array<['string', 'null']>`
      - `confirmed_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `header_fingerprint` *required*: `string`
        - type: `string`
      - `header_texts` *required*: `array<string>`
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `row_rules` *required*: `any`
        - type: `any`
      - `source_job_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `404`: Absent or outside the caller's scope

### `PATCH /v1/ocr/table-templates/{template_id}`

- operationId: `updateOcrTableTemplate`
- tags: `OCR v1`
- parameters:
  - `template_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `column_keys`: `['object', 'null']`
      - description: Column index (a decimal string, from 0) to the key that column fills.
      - type: `['object', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Updated template
    - `application/json`:
      - type: `object (16 properties)`
      - `column_bounds` *required*: `array<array<number>>`
        - type: `array<array<number>>`
      - `column_count` *required*: `integer`
        - type: `integer`
      - `column_keys` *required*: `array<['string', 'null']>`
        - type: `array<['string', 'null']>`
      - `confirmed_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `header_fingerprint` *required*: `string`
        - type: `string`
      - `header_texts` *required*: `array<string>`
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `row_rules` *required*: `any`
        - type: `any`
      - `source_job_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `404`: Absent or outside the caller's scope

### `DELETE /v1/ocr/table-templates/{template_id}`

- operationId: `deleteOcrTableTemplate`
- tags: `OCR v1`
- parameters:
  - `template_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Deleted
  - `404`: Absent or outside the caller's scope

### `POST /v1/ocr/table-templates/{template_id}/confirm`

- operationId: `confirmOcrTableTemplate`
- tags: `OCR v1`
- parameters:
  - `template_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Confirmation recorded
    - `application/json`:
      - type: `object (16 properties)`
      - `column_bounds` *required*: `array<array<number>>`
        - type: `array<array<number>>`
      - `column_count` *required*: `integer`
        - type: `integer`
      - `column_keys` *required*: `array<['string', 'null']>`
        - type: `array<['string', 'null']>`
      - `confirmed_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `header_fingerprint` *required*: `string`
        - type: `string`
      - `header_texts` *required*: `array<string>`
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `row_rules` *required*: `any`
        - type: `any`
      - `source_job_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `404`: Absent or outside the caller's scope

### `GET /v1/ocr/webhooks`

- operationId: `listOcrWebhooks`
- tags: `OCR v1`
- parameters:
  - `project_id` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Project endpoints; no secrets
    - `application/json`:
      - type: `array<object (5 properties)>`

### `POST /v1/ocr/webhooks`

- operationId: `createOcrWebhook`
- tags: `OCR v1`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `events` *required*: `array<string>`
      - type: `array<string>`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `url` *required*: `string`
      - type: `string`
- responses:
  - `201`: Endpoint created; secret shown once
    - `application/json`:
      - type: `object (2 properties)`
      - `endpoint` *required*: `object (5 properties)`
        - type: `object (5 properties)`
      - `secret` *required*: `string`
        - type: `string`
  - `400`: Invalid events or refused target URL
  - `403`: Admin permission required

### `DELETE /v1/ocr/webhooks/{id}`

- operationId: `deleteOcrWebhook`
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Endpoint and delivery log deleted
  - `404`: Not found

### `GET /v1/ocr/webhooks/{id}/deliveries`

- operationId: `listOcrWebhookDeliveries`
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Last 100 deliveries
    - `application/json`:
      - type: `array<object (9 properties)>`

### `POST /v1/ocr/webhooks/{id}/rotate-secret`

- operationId: `rotateOcrWebhookSecret`
- tags: `OCR v1`
- parameters:
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: New secret shown once; previous signs for 24 hours
    - `application/json`:
      - type: `object (2 properties)`
      - `endpoint` *required*: `object (5 properties)`
        - type: `object (5 properties)`
      - `secret` *required*: `string`
        - type: `string`

### `GET /v1/onboarding/next-actions`

- operationId: `onboarding_next_actions`
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `actions` *required*: `array<string>`
        - type: `array<string>`
      - `can_create_organization` *required*: `boolean`
        - type: `boolean`
      - `email_verified` *required*: `boolean`
        - type: `boolean`
      - `has_organizations` *required*: `boolean`
        - type: `boolean`
      - `organization_policy` *required*: `string`
        - description: Minimal install policy safe to publish without tenant counts or names.
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}`

- operationId: `get_organization`
- summary: Read one organization by slug.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}`

- operationId: `update_organization`
- summary: Update one organization's settings.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `brand_accent_color`: `['string', 'null']`
      - type: `['string', 'null']`
    - `brand_primary_color`: `['string', 'null']`
      - type: `['string', 'null']`
    - `logo_blob_key`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `quota_max_containers`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `quota_max_disk_mb`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `quota_max_projects`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `status`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}`

- operationId: `delete_organization`
- summary: Soft-delete one organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Organization delete refused, nothing deleted: it still owns managed services (problem type `https://conusai.com/probs/organization-delete-blocked`, naming each; delete them first, which stops and removes their containers), it still has projects (delete them, or their workspaces, first), or it owns the platform's vendor Git service
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/ai/app-actions/proposals`

- operationId: `propose`
- tags: `AI tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `binding_id` *required*: `string`
      - type: `string`
    - `input` *required*: `object`
      - type: `object`
    - `procedure` *required*: `string`
      - type: `string`
    - `project_slug`: `['string', 'null']`
      - type: `['string', 'null']`
    - `version` *required*: `integer`
      - type: `integer`
    - `workspace_slug`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (6 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `expires_at_micros` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `procedure` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `version` *required*: `integer`
        - type: `integer`
  - `503`: Actual Root authority unavailable

### `POST /v1/orgs/{org_slug}/ai/app-actions/{action_id}/decision`

- operationId: `decide`
- tags: `AI tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `action_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `decision_evidence` *required*: `object (3 properties)`
      - type: `object (3 properties)`
    - `decision_signature` *required*: `string`
      - type: `string`
    - `encoded_request` *required*: `object (6 properties)`
      - type: `object (6 properties)`
    - `request` *required*: `object (16 properties)`
      - type: `object (16 properties)`
    - `root_signature` *required*: `string`
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (8 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `decision_sha256` *required*: `string`
        - type: `string`
      - `dispatch_challenge`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `expires_at_micros` *required*: `string`
        - type: `string`
      - `source_epoch` *required*: `string`
        - type: `string`
      - `source_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `version` *required*: `integer`
        - type: `integer`
  - `503`: Actual Root authority unavailable

### `POST /v1/orgs/{org_slug}/ai/app-actions/{action_id}/redeem`

- operationId: `redeem`
- tags: `AI tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `action_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `encoded_request` *required*: `object (6 properties)`
      - type: `object (6 properties)`
    - `host_signature` *required*: `string`
      - type: `string`
    - `observation` *required*: `object (24 properties)`
      - type: `object (24 properties)`
    - `request` *required*: `object (16 properties)`
      - type: `object (16 properties)`
    - `root_signature` *required*: `string`
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (9 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `dispatch_lease_id` *required*: `string`
        - type: `string`
      - `execution_context` *required*: `string`
        - type: `string`
      - `expires_at_micros` *required*: `string`
        - type: `string`
      - `observation_sha256` *required*: `string`
        - type: `string`
      - `redeemed` *required*: `boolean`
        - type: `boolean`
      - `source_epoch` *required*: `string`
        - type: `string`
      - `source_id` *required*: `string`
        - type: `string`
      - `version` *required*: `integer`
        - type: `integer`
  - `503`: Actual Root authority unavailable

### `POST /v1/orgs/{org_slug}/ai/app-actions/{action_id}/view`

- operationId: `view`
- tags: `AI tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `action_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `action_id` *required*: `string`
      - type: `string`
    - `version` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (18 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `binding_id` *required*: `string`
        - type: `string`
      - `created_at_micros` *required*: `string`
        - type: `string`
      - `decision_challenges`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `dispatch_challenge`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `encoded_request` *required*: `object (6 properties)`
        - type: `object (6 properties)`
      - `expires_at_micros` *required*: `string`
        - type: `string`
      - `input` *required*: `object`
        - type: `object`
      - `owner` *required*: `string`
        - type: `string`
      - `procedure` *required*: `string`
        - type: `string`
      - `project_slug`: `['string', 'null']`
        - type: `['string', 'null']`
      - `result` *required*: `any`
        - type: `any`
      - `source_epoch` *required*: `string`
        - type: `string`
      - `source_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `tool` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `version` *required*: `integer`
        - type: `integer`
      - `workspace_slug`: `['string', 'null']`
        - type: `['string', 'null']`
  - `503`: Actual Root authority unavailable

### `GET /v1/orgs/{org_slug}/ai/providers`

- operationId: `list_provider_keys`
- summary: List the AI provider keys of one organization.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of provider keys
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/ai/providers`

- operationId: `create_provider_key`
- summary: Create an AI provider key in one organization.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `api_key` *required*: `string`
      - type: `string`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `default_model`: `['string', 'null']`
      - description: Optional model id to pin for this provider (e.g. "gpt-4o-mini").
      - type: `['string', 'null']`
    - `display_name` *required*: `string`
      - type: `string`
    - `processing_region`: `['string', 'null']`
      - description: Declared processing region (`eu`, `us`, `global`, `unknown`).
      - type: `['string', 'null']`
    - `provider` *required*: `string`
      - type: `string`
- responses:
  - `201`: Provider key created
    - `application/json`:
      - type: `object (10 properties)`
      - `api_key_masked` *required*: `string`
        - description: Masked API key (only last 4 chars visible)
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `default_model`: `['string', 'null']`
        - description: Model id this provider serves (NULL → per-provider default).
        - type: `['string', 'null']`
      - `display_name` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `processing_region` *required*: `string`
        - description: The organization's declared processing region (`eu`, `us`, `global`,
        - type: `string`
      - `provider` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/ai/providers/{id}`

- operationId: `update_provider_key`
- summary: Update one AI provider key.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `api_key`: `['string', 'null']`
      - type: `['string', 'null']`
    - `base_url`: `['string', 'null']`
      - description: Double-Option: absent = leave unchanged, present-null = clear (revert to
      - type: `['string', 'null']`
    - `default_model`: `['string', 'null']`
      - description: Double-Option: absent = leave unchanged, present-null = clear the pinned
      - type: `['string', 'null']`
    - `display_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_active`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `processing_region`: `['string', 'null']`
      - description: Double-Option: absent = leave unchanged, present-null = revert to
      - type: `['string', 'null']`
- responses:
  - `200`: Provider key updated
    - `application/json`:
      - type: `object (10 properties)`
      - `api_key_masked` *required*: `string`
        - description: Masked API key (only last 4 chars visible)
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `default_model`: `['string', 'null']`
        - description: Model id this provider serves (NULL → per-provider default).
        - type: `['string', 'null']`
      - `display_name` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `processing_region` *required*: `string`
        - description: The organization's declared processing region (`eu`, `us`, `global`,
        - type: `string`
      - `provider` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Provider key or organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/ai/providers/{id}`

- operationId: `delete_provider_key`
- summary: Delete one AI provider key.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Provider key deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Provider key or organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/ai/providers/{id}/test`

- operationId: `test_provider_key_by_id`
- summary: Test one stored AI provider key against its upstream.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Test result
    - `application/json`:
      - type: `object (4 properties)`
      - `error`: `['string', 'null']`
        - description: Error message if the test failed
        - type: `['string', 'null']`
      - `latency_ms` *required*: `integer`
        - description: Response time in milliseconds
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Provider key or organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/by-provider`

- operationId: `get_usage_by_provider`
- summary: Usage broken down by provider.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `user_id` (query): `integer`
  - `conversation_id` (query): `string`
  - `tags` (query): `string`
  - `model` (query): `string`
  - `provider` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Usage broken down by provider
    - `application/json`:
      - type: `array<object (6 properties)>`
  - `400`: Invalid query parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/conversations`

- operationId: `get_conversations`
- summary: Conversation summaries for one organization.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `limit` (query): `integer`
  - `user_id` (query): `integer`
  - `conversation_id` (query): `string`
  - `tags` (query): `string`
  - `model` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Conversation summaries
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `400`: Invalid query parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/conversations/{conversation_id}`

- operationId: `get_conversation_detail`
- summary: The invocations within one conversation.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `conversation_id` (path) *required*: `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Invocations within a conversation
    - `application/json`:
      - type: `array<object (30 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/errors`

- operationId: `get_usage_errors`
- summary: Failed AI attempts for one organization.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `request_id` (query): `string`
  - `status` (query): `integer`
  - `provider` (query): `string`
  - `model` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Failed attempts with status >= 400
    - `application/json`:
      - type: `object (2 properties)`
      - `entries` *required*: `array<object (30 properties)>`
        - description: The usage log entries for the requested page.
        - type: `array<object (30 properties)>`
      - `total` *required*: `integer`
        - description: Total number of entries matching the filter (across all pages).
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/recent`

- operationId: `get_usage_recent`
- summary: A page of recent AI invocations.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `user_id` (query): `integer`
  - `conversation_id` (query): `string`
  - `tags` (query): `string`
  - `provider` (query): `string`
  - `model` (query): `string`
  - `status` (query): `integer`
  - `cost_gte` (query): `integer`
  - `cost_gt` (query): `integer`
  - `cost_lte` (query): `integer`
  - `cost_lt` (query): `integer`
  - `tokens_gte` (query): `integer`
  - `tokens_gt` (query): `integer`
  - `tokens_lte` (query): `integer`
  - `tokens_lt` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Page of recent usage log entries
    - `application/json`:
      - type: `object (2 properties)`
      - `entries` *required*: `array<object (30 properties)>`
        - description: The usage log entries for the requested page.
        - type: `array<object (30 properties)>`
      - `total` *required*: `integer`
        - description: Total number of entries matching the filter (across all pages).
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/summary`

- operationId: `get_usage_summary`
- summary: Usage summary for one organization over a time range.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `user_id` (query): `integer`
  - `conversation_id` (query): `string`
  - `tags` (query): `string`
  - `model` (query): `string`
  - `provider` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Usage summary for the time range
    - `application/json`:
      - type: `object (13 properties)`
      - `avg_latency_ms` *required*: `number`
        - type: `number`
      - `byok_count` *required*: `integer`
        - type: `integer`
      - `error_count` *required*: `integer`
        - type: `integer`
      - `p50_latency_ms` *required*: `number`
        - type: `number`
      - `p50_ttft_ms`: `['number', 'null']`
        - type: `['number', 'null']`
      - `p95_latency_ms` *required*: `number`
        - type: `number`
      - `p95_ttft_ms`: `['number', 'null']`
        - type: `['number', 'null']`
      - `streaming_count` *required*: `integer`
        - type: `integer`
      - `total_cost_microcents` *required*: `integer`
        - type: `integer`
      - `total_input_tokens` *required*: `integer`
        - type: `integer`
      - `total_output_tokens` *required*: `integer`
        - type: `integer`
      - `total_requests` *required*: `integer`
        - type: `integer`
      - `total_tokens` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/timeseries`

- operationId: `get_usage_timeseries`
- summary: Time-series usage for one organization.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `bucket` (query): `string`
  - `user_id` (query): `integer`
  - `conversation_id` (query): `string`
  - `tags` (query): `string`
  - `model` (query): `string`
  - `provider` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Time-series usage data
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `400`: Invalid query parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/ai/usage/top-models`

- operationId: `get_usage_top_models`
- summary: Top models by request count.
- tags: `AI Gateway v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `limit` (query): `integer`
  - `user_id` (query): `integer`
  - `tags` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Top models by request count
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `400`: Invalid query parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/analytics/general-stats`

- operationId: `get_general_stats`
- summary: Organization-wide analytics totals for one path-scoped organization.
- description: The org twin of the project-tier routes above. It delegates to the legacy
handler with [`OrgScope::active_org`], so `permission_guard!`,
`deny_deployment_token!` and the org-scoped aggregation in
`analytics_service::get_general_stats` stay one implementation. The only
thing that changes is where the organization came from: a path segment
resolved against `organization_members`, instead of the caller's active-org
header claim.

There is no `Path` extractor here on purpose. The URI's only capture is
`{org_slug}`, which `OrgScope` consumes; adding a bare `Path<String>` would
deserialize *that slug* and hand it back as if it were a resource id — a
**200** with the wrong value, not a loud failure. See
`org_prefix_arity_tests`.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved general statistics
    - `application/json`:
      - type: `object (12 properties)`
      - `avg_bounce_rate` *required*: `number`
        - type: `number`
      - `avg_engagement_rate` *required*: `number`
        - type: `number`
      - `page_views_trend_percentage`: `['number', 'null']`
        - description: Percentage change in page views vs previous period
        - type: `['number', 'null']`
      - `previous_page_views`: `['integer', 'null']`
        - description: Previous period page views
        - type: `['integer', 'null']`
      - `previous_unique_visitors`: `['integer', 'null']`
        - description: Previous period unique visitors (same duration, shifted back)
        - type: `['integer', 'null']`
      - `project_breakdown` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `total_events` *required*: `integer`
        - type: `integer`
      - `total_page_views` *required*: `integer`
        - type: `integer`
      - `total_projects` *required*: `integer`
        - type: `integer`
      - `total_unique_visitors` *required*: `integer`
        - type: `integer`
      - `total_visits` *required*: `integer`
        - type: `integer`
      - `visitors_trend_percentage`: `['number', 'null']`
        - description: Percentage change in unique visitors vs previous period
        - type: `['number', 'null']`
  - `400`: Invalid date format or parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found for this caller
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/api-keys`

- operationId: `list_api_keys`
- summary: Lists the API keys of the organization named by the path (the
`kernel.api_key` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: API keys retrieved successfully
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid collection query (`urn:conusai:collections:*`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/api-keys`

- operationId: `create_api_key`
- summary: Creates a new API key in the organization named by the path.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `expires_at`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `permissions`: `['array', 'null']`
      - type: `['array', 'null']`
    - `role_type` *required*: `string`
      - description: Platform role or organization role. Org roles stay within the key's
      - type: `string`
    - `token_class`: `['string', 'null']`
      - description: Token class: `personal` (default) or `org`. `service_ingest` is
      - type: `['string', 'null']`
- responses:
  - `201`: API key created successfully
    - `application/json`:
      - type: `object (11 properties)`
      - `api_key` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `409`: Conflict - API key name already exists
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/api-keys/_batch`

- operationId: `get_api_keys_batch`
- summary: Read back API keys of the organization by id.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible API keys among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/api-keys/permissions`

- operationId: `get_api_key_permissions`
- summary: Lists the permissions and roles available for scoping API keys.
- description: The instance-wide catalogue takes no [`OrgPathScope`] even though it sits
under the org prefix: there is nothing tenant-specific to prove. The
`org_slug` segment is part of the route shape — one grammar — and is
simply not extracted here.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Available permissions and roles retrieved successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `permissions` *required*: `array<object (7 properties)>`
        - description: All available permissions in the system
        - type: `array<object (7 properties)>`
      - `roles` *required*: `array<object (3 properties)>`
        - description: All available roles
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/api-keys/{id}`

- operationId: `get_api_key`
- summary: Fetches a single API key of the organization named by the path.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: API key retrieved successfully
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/api-keys/{id}`

- operationId: `update_api_key`
- summary: Updates an API key's metadata within the organization named by the path.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `expires_at`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_active`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `permissions`: `['array', 'null']`
      - type: `['array', 'null']`
- responses:
  - `200`: API key updated successfully
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/api-keys/{id}`

- operationId: `delete_api_key`
- summary: Permanently deletes an API key of the organization named by the path.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: API key deleted successfully
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/api-keys/{id}/activate`

- operationId: `activate_api_key`
- summary: Reactivates a previously deactivated API key.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: API key activated successfully
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/api-keys/{id}/deactivate`

- operationId: `deactivate_api_key`
- summary: Deactivates an API key without deleting it.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: API key deactivated successfully
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/api-keys/{id}/rotate`

- operationId: `rotate_api_key`
- summary: Rotates an API key's secret, returning the new plaintext value once.
- tags: `API Keys`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: API key rotated successfully; the response contains the new plaintext secret, shown only once
    - `application/json`:
      - type: `object (11 properties)`
      - `api_key` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `key_last4`: `['string', 'null']`
        - type: `['string', 'null']`
      - `key_prefix` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `role_type` *required*: `string`
        - type: `string`
      - `token_class` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/app-bindings/lookup`

- operationId: `lookup_binding`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `app_tenant_id` *required*: `string`
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `app_tenant_id` *required*: `string`
        - type: `string`
      - `binding_id` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `environment_uuid` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `partition_major` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
  - `403`: Server project credential required
  - `404`: No active binding in this exact authority
  - `503`: Control plane unavailable

### `GET /v1/orgs/{org_slug}/app-bindings/{binding_id}`

- operationId: `get_binding`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `binding_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `app_tenant_id` *required*: `string`
        - type: `string`
      - `binding_id` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `environment_uuid` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `partition_major` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
  - `403`: Server project credential required or binding revoked
  - `404`: No binding in this exact authority

### `POST /v1/orgs/{org_slug}/app-bindings/{binding_id}/services/{service}/admission`

- operationId: `service_admission`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `binding_id` (path) *required*: `string`
  - `service` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `scopes` *required*: `array<string>`
      - description: The exact scopes of the one operation the app is about to dispatch, all of
      - type: `array<string>`
- responses:
  - `200`: Current admission facts for this binding and operation; unknown never admits
    - `application/json`:
      - type: `object (10 properties)`
      - `authorized` *required*: `string`
        - type: `string`
      - `binding` *required*: `object (7 properties)`
        - type: `object (7 properties)`
      - `compatible` *required*: `string`
        - type: `string`
      - `component` *required*: `object (14 properties)`
        - type: `object (14 properties)`
      - `configured` *required*: `string`
        - type: `string`
      - `dependencies_ready` *required*: `string`
        - type: `string`
      - `observed_at` *required*: `string`
        - description: When these facts were collected, after the collector's final re-check.
        - type: `string`
      - `partition_bound` *required*: `string`
        - type: `string`
      - `ready` *required*: `string`
        - type: `string`
      - `reason_codes` *required*: `array<string>`
        - description: Why admission is refused or unknown, closed and value-free; empty when admitted.
        - type: `array<string>`
  - `400`: Invalid binding id or scopes
  - `401`: No valid credential
  - `403`: Server project credential required or binding revoked
  - `404`: Foreign organization, no binding in this exact authority, or the service is not installed
  - `409`: Credential without a deployment environment
  - `413`: Request body over 32 KiB
  - `503`: Control plane unavailable

### `GET /v1/orgs/{org_slug}/audit/checkpoints`

- operationId: `list_checkpoints_v2`
- summary: List an organization's signed checkpoints, newest first.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `limit` (query): `integer`
  - `before_seq` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Signed checkpoints, newest first, each with its C2SP note
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/checkpoints/latest`

- operationId: `latest_checkpoint_v2`
- summary: Read the latest signed checkpoint of an organization.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The newest signed checkpoint, with its C2SP note
    - `application/json`:
      - type: `object (8 properties)`
      - `global_chain_seq` *required*: `integer`
        - description: The global chain position when this checkpoint was signed
        - type: `integer`
      - `id` *required*: `integer`
        - description: `audit_checkpoints` primary key
        - type: `integer`
      - `kid` *required*: `string`
        - description: Key id: first 8 bytes of SHA-256(verifying key), hex (D8)
        - type: `string`
      - `note` *required*: `string`
        - description: The C2SP-style signed note, ready to save and verify offline (D19)
        - type: `string`
      - `org_chain_hash_b64` *required*: `string`
        - description: Base64 of the org chain hash at `org_seq`
        - type: `string`
      - `org_seq` *required*: `integer`
        - description: The org sub-chain position this checkpoint attests
        - type: `integer`
      - `signature_b64` *required*: `string`
        - description: Base64 of the Ed25519 signature over the canonical body
        - type: `string`
      - `signed_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found, or no checkpoint yet
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/events`

- operationId: `list_audit_events_v2`
- summary: List an organization's audit events, newest first, cursor-paginated.
- description: `concise` (default) returns what an agent needs to scan; `detailed` adds
every projection, the subject, the correlation ids and server-computed
`links` that are present only when their target row exists. Reads are
themselves audited (AU-9).
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `cursor` (query): `string`
  - `limit` (query): `integer`
  - `project_id` (query): `integer`
  - `workspace_id` (query): `string`
  - `source` (query): `string`
  - `actor_kind` (query): `string`
  - `actor_id` (query): `string`
  - `delegator_id` (query): `string`
  - `action` (query): `string`
  - `outcome` (query): `string`
  - `class` (query): `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `correlation_id` (query): `string`
  - `session_id` (query): `string`
  - `trace_id` (query): `string`
  - `request_id` (query): `string`
  - `replay_id` (query): `string`
  - `category` (query): `string`
  - `app_tenant` (query): `string`
  - `resource_type` (query): `string`
  - `resource_id` (query): `string`
  - `response_format` (query): `string`
  - `include_payload` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: One page of events, newest first
    - `application/json`:
      - type: `object (3 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<any | object (9 properties)>`
        - type: `array<any | object (9 properties)>`
      - `next_cursor`: `['string', 'null']`
        - description: Pass back as `cursor` for the next page; `null` on the last page
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: Malformed cursor or filter
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/events/{event_id}`

- operationId: `get_audit_event_v2`
- summary: Read one audit event in the detailed shape: the subject revealed inline
unless erased, and the replay / request-log / trace links that exist.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `event_id` (path) *required*: `integer`
  - `include_payload` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: The event, detailed
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization or event not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/export-sinks`

- operationId: `list_sinks_v2`
- summary: List the organization's export sinks, oldest first.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The org's export sinks; secrets are write-only and never appear
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/audit/export-sinks`

- operationId: `create_sink_v2`
- summary: Create an export sink. The config is validated to the kind's shape and
through the sink's own constructor (a config that could never deliver is
a 422, not a stored dead-letter), encrypted with the platform
`EncryptionService`, and never returned — the 201 carries the redacted
view. A duplicate `(org, name)` is a 409.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `config` *required*: `any`
      - description: The kind's full config JSON (webhook: `url` + `secret`; s3: `bucket`,
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - description: Defaults to `true`
      - type: `['boolean', 'null']`
    - `format`: `['string', 'null']`
      - description: `native` (the default) or `ocsf`
      - type: `['string', 'null']`
    - `kind` *required*: `string`
      - description: `webhook`, `s3` or `otlp`
      - type: `string`
    - `name` *required*: `string`
      - description: The operator-given name; unique per org
      - type: `string`
- responses:
  - `201`: The created sink, secrets redacted
    - `application/json`:
      - type: `object (11 properties)`
      - `config` *required*: `any`
        - description: The non-secret config fields only (the webhook `url`, the s3
        - type: `any`
      - `created_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `format` *required*: `string`
        - description: `native` (`CloudEvents` 1.0) or `ocsf`
        - type: `string`
      - `header_names` *required*: `array<string>`
        - description: The configured otlp header *names* — names only, never values
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - description: `webhook`, `s3` or `otlp`
        - type: `string`
      - `last_enqueued_org_seq` *required*: `integer`
        - description: The enqueue high-water mark: the checkpointed org sub-chain position
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `secret_set` *required*: `boolean`
        - description: Whether the kind's secret material is set (the value is write-only)
        - type: `boolean`
      - `updated_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization not found
  - `409`: A sink with this name already exists
  - `422`: Invalid kind, format or config
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/export-sinks/{sink_id}`

- operationId: `get_sink_v2`
- summary: Read one export sink. A cross-org id is 404, indistinguishable from
absent.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `sink_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The sink, secrets redacted
    - `application/json`:
      - type: `object (11 properties)`
      - `config` *required*: `any`
        - description: The non-secret config fields only (the webhook `url`, the s3
        - type: `any`
      - `created_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `format` *required*: `string`
        - description: `native` (`CloudEvents` 1.0) or `ocsf`
        - type: `string`
      - `header_names` *required*: `array<string>`
        - description: The configured otlp header *names* — names only, never values
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - description: `webhook`, `s3` or `otlp`
        - type: `string`
      - `last_enqueued_org_seq` *required*: `integer`
        - description: The enqueue high-water mark: the checkpointed org sub-chain position
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `secret_set` *required*: `boolean`
        - description: Whether the kind's secret material is set (the value is write-only)
        - type: `boolean`
      - `updated_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization or sink not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/audit/export-sinks/{sink_id}`

- operationId: `update_sink_v2`
- summary: Patch one export sink. An omitted `config` leaves the stored secrets
alone; a present one replaces them wholesale.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `sink_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `config`: `any`
      - description: The kind's full config JSON, secrets included
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `format`: `['string', 'null']`
      - description: `native` or `ocsf`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: The updated sink, secrets redacted
    - `application/json`:
      - type: `object (11 properties)`
      - `config` *required*: `any`
        - description: The non-secret config fields only (the webhook `url`, the s3
        - type: `any`
      - `created_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `format` *required*: `string`
        - description: `native` (`CloudEvents` 1.0) or `ocsf`
        - type: `string`
      - `header_names` *required*: `array<string>`
        - description: The configured otlp header *names* — names only, never values
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - description: `webhook`, `s3` or `otlp`
        - type: `string`
      - `last_enqueued_org_seq` *required*: `integer`
        - description: The enqueue high-water mark: the checkpointed org sub-chain position
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `secret_set` *required*: `boolean`
        - description: Whether the kind's secret material is set (the value is write-only)
        - type: `boolean`
      - `updated_at` *required*: `string`
        - description: RFC 3339 UTC, microsecond precision
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization or sink not found
  - `409`: The rename collides with another sink
  - `422`: Invalid format or config
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/audit/export-sinks/{sink_id}`

- operationId: `delete_sink_v2`
- summary: Delete one export sink; its pending outbox rows cascade with it. 204.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `sink_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: The sink and its pending deliveries are gone
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization or sink not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/audit/export-sinks/{sink_id}/test`

- operationId: `test_sink_v2`
- summary: Deliver a synthetic one-event batch through the sink, synchronously (C9):
the event is clearly marked (`audit.sink.test`, actor kind `service`,
`data.synthetic: true`) and never enters the audit log — it exists only
on the wire. The outcome is the sink's own: delivered is a 200 with
`delivered: true`; a permanent rejection is a 200 with `delivered:
false` and the sink's reason (a status, never the receiver's body); a
retryable failure is a 502 — the tenant should fix nothing, the sink is
temporarily down. A stored config that no longer decrypts or parses is a
422, and nothing is delivered.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `sink_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The synchronous delivery outcome
    - `application/json`:
      - type: `object (2 properties)`
      - `delivered` *required*: `boolean`
        - type: `boolean`
      - `error`: `['string', 'null']`
        - description: The sink's own reason when `delivered` is false
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization or sink not found
  - `422`: The stored config is undeliverable
  - `500`: Internal server error
  - `502`: The sink reported a retryable failure

### `GET /v1/orgs/{org_slug}/audit/logs`

- operationId: `list_audit_logs`
- summary: List an organization's audit logs, with optional filtering.
- tags: `Audit Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `operation_type` (query): `string`
  - `user_id` (query): `integer`
  - `from` (query): `string`
  - `to` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of audit logs
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/logs/{id}`

- operationId: `get_audit_log`
- summary: Read one audit log entry inside one organization.
- tags: `Audit Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Audit log details
    - `application/json`:
      - type: `object (7 properties)`
      - `audit_date` *required*: `integer`
        - description: When the action occurred
        - type: `integer`
      - `data`: `any`
        - description: Additional context about the action
        - type: `any`
      - `id` *required*: `integer`
        - description: Unique identifier for the audit log entry
        - type: `integer`
      - `ip_address`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `operation_type` *required*: `string`
        - description: The type of action that was performed
        - type: `string`
      - `user`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `user_id`: `['integer', 'null']`
        - description: The user who performed the action (`null` when that account has
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Audit log not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/retention`

- operationId: `get_retention_v2`
- summary: Read the organization-wide retention tiers. With no stored row the
response carries the effective defaults (`configured: false`) — a tenant
always has retention, stored or not.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The org-wide retention tiers (or the effective defaults)
    - `application/json`:
      - type: `object (7 properties)`
      - `access_enabled` *required*: `boolean`
        - description: Whether access-tier pruning is on for this scope (opt-in)
        - type: `boolean`
      - `access_retain_days` *required*: `integer`
        - description: Days access-class rows are kept; never below 1
        - type: `integer`
      - `admin_retain_days` *required*: `integer`
        - description: Days admin-class rows are kept; never below 365 (NIST AU-11 floor)
        - type: `integer`
      - `configured` *required*: `boolean`
        - description: `false` when no row is stored and the values are the defaults
        - type: `boolean`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - description: `null` on the org-wide row; the path's project on the project route
        - type: `['integer', 'null']`
      - `updated_at`: `['string', 'null']`
        - description: RFC 3339 UTC of the last write; `null` when `configured` is false
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/audit/retention`

- operationId: `put_retention_v2`
- summary: Write the organization-wide retention tiers. Both floors are enforced
(`admin_retain_days >= 365`, `access_retain_days >= 1`); a violation is a
422 naming the floor. DELETE is deliberately not offered.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `access_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `access_retain_days` *required*: `integer`
      - type: `integer`
    - `admin_retain_days` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: The stored org-wide tiers
    - `application/json`:
      - type: `object (7 properties)`
      - `access_enabled` *required*: `boolean`
        - description: Whether access-tier pruning is on for this scope (opt-in)
        - type: `boolean`
      - `access_retain_days` *required*: `integer`
        - description: Days access-class rows are kept; never below 1
        - type: `integer`
      - `admin_retain_days` *required*: `integer`
        - description: Days admin-class rows are kept; never below 365 (NIST AU-11 floor)
        - type: `integer`
      - `configured` *required*: `boolean`
        - description: `false` when no row is stored and the values are the defaults
        - type: `boolean`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - description: `null` on the org-wide row; the path's project on the project route
        - type: `['integer', 'null']`
      - `updated_at`: `['string', 'null']`
        - description: RFC 3339 UTC of the last write; `null` when `configured` is false
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization not found
  - `422`: Below the D13 floors
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/audit/settings`

- operationId: `get_settings_v2`
- summary: Read the D20 settings: the per-org ingest budget override and the access
flag of the org-wide row.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The org's audit settings
    - `application/json`:
      - type: `object (2 properties)`
      - `access_enabled` *required*: `boolean`
        - type: `boolean`
      - `ingest_events_per_minute`: `['integer', 'null']`
        - description: The per-org ingest budget override in events/minute; `null` applies
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/audit/settings`

- operationId: `put_settings_v2`
- summary: Write the D20 settings. `ingest_events_per_minute` above the operator cap
(`MAX_INGEST_EVENTS_PER_MINUTE_OVERRIDE`, 100 000) or below 1 is a 422;
`null` clears the override. The retention tiers on the same row are
untouched — the two PUTs own disjoint columns.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `access_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `ingest_events_per_minute`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: The stored settings
    - `application/json`:
      - type: `object (2 properties)`
      - `access_enabled` *required*: `boolean`
        - type: `boolean`
      - `ingest_events_per_minute`: `['integer', 'null']`
        - description: The per-org ingest budget override in events/minute; `null` applies
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization not found
  - `422`: Override above the operator cap or below 1
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/audit/subjects/{subject_id}/erase`

- operationId: `erase_subject_v2`
- summary: Shred PII for one subject across the organization (§2). The audit rows stay
untouched — they never held the PII — so the org sub-chain and its
checkpoints verify green across an erasure. Idempotent: re-erasing an
erased subject is a 204 again and appends no second tombstone.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `subject_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: The subject's PII is shredded (idempotent: re-erasing is still 204)
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization or subject not found

### `GET /v1/orgs/{org_slug}/audit/verify`

- operationId: `verify_v2`
- summary: Verify the organization's sub-chain on demand: `org_seq` continuity,
prev-hash linkage, recomputed hashes and every checkpoint signature in the
window. A red chain is a 200 with `ok: false` — the divergence is the
result, not a transport failure.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `from_seq` (query): `integer`
  - `to_seq` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: The verification report; `ok: false` means the chain diverges
    - `application/json`:
      - type: `object (7 properties)`
      - `checked` *required*: `integer`
        - description: Stamped org rows examined
        - type: `integer`
      - `checkpoints_verified` *required*: `integer`
        - description: Checkpoints in the window whose signature verified and whose hash
        - type: `integer`
      - `divergence`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `first_org_seq`: `['integer', 'null']`
        - description: Lowest and highest `org_seq` examined, when anything was
        - type: `['integer', 'null']`
      - `last_org_chain_hash`: `['string', 'null']`
        - description: The last verified `org_chain_hash`, hex — the org head
        - type: `['string', 'null']`
      - `last_org_seq`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `ok` *required*: `boolean`
        - description: `true` when nothing in the window contradicts the sub-chain
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/alerts`

- operationId: `list_backup_alerts`
- summary: List the open backup alerts of one organization.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Open backup alerts
    - `application/json`:
      - type: `object (1 properties)`
      - `alerts` *required*: `array<object (8 properties)>`
        - description: All currently open (unresolved) alerts, newest first.
        - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/retention/run`

- operationId: `run_retention`
- summary: Run backup retention for this organization now.
- description: Deletes this organization's expired scheduled backups (with the WAL-G
WAL no kept base backup needs), its failed backup rows older than seven
days and its ad-hoc backups older than 90 days except the newest of each
service, and answers the counts. A row whose deletion fails is left for
the next pass.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: What the run deleted
    - `application/json`:
      - type: `object (5 properties)`
      - `ad_hoc_deleted` *required*: `integer`
        - description: Expired ad-hoc backups deleted.
        - type: `integer`
      - `expired_backups_deleted` *required*: `integer`
        - description: Expired completed backups whose storage and row were deleted.
        - type: `integer`
      - `failed_rows_deleted` *required*: `integer`
        - description: Failed backup rows deleted with their partial objects.
        - type: `integer`
      - `kept_for_dependency` *required*: `integer`
        - description: Expired WAL-G backups kept, with their rows, because a delta backup
        - type: `integer`
      - `wal_segments_deleted` *required*: `integer`
        - description: `wal_005/` objects deleted from WAL-G prefixes because no remaining
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient organization permissions (needs backups:write)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: A retention run of this organization is already in progress (`urn:conusai:backup:retention-run-in-progress`)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/backups/s3-sources`

- operationId: `list_s3_sources`
- summary: List an organization's S3 sources.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of S3 sources
    - `application/json`:
      - type: `array<object (12 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/s3-sources`

- operationId: `create_s3_source`
- summary: Create an S3 source in an organization.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `access_key_id` *required*: `string`
      - type: `string`
    - `bucket_name` *required*: `string`
      - type: `string`
    - `bucket_path` *required*: `string`
      - type: `string`
    - `endpoint`: `['string', 'null']`
      - description: Optional endpoint URL for a self-hosted S3 service
      - type: `['string', 'null']`
    - `force_path_style`: `['boolean', 'null']`
      - description: Whether to use path-style addressing (default: true)
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - description: When true, make this the default source (will swap out any existing default).
      - type: `['boolean', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `region` *required*: `string`
      - type: `string`
    - `secret_key` *required*: `string`
      - type: `string`
- responses:
  - `201`: S3 source created
    - `application/json`:
      - type: `object (12 properties)`
      - `access_key_id` *required*: `string`
        - type: `string`
      - `bucket_name` *required*: `string`
        - type: `string`
      - `bucket_path` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `endpoint`: `['string', 'null']`
        - type: `['string', 'null']`
      - `force_path_style` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `secret_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/s3-sources/test`

- operationId: `test_s3_connection_preview`
- summary: Test a prospective S3 configuration without persisting it.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `access_key_id` *required*: `string`
      - type: `string`
    - `bucket_name` *required*: `string`
      - type: `string`
    - `bucket_path` *required*: `string`
      - type: `string`
    - `endpoint`: `['string', 'null']`
      - description: Optional endpoint URL for a self-hosted S3 service
      - type: `['string', 'null']`
    - `force_path_style`: `['boolean', 'null']`
      - description: Whether to use path-style addressing (default: true)
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - description: When true, make this the default source (will swap out any existing default).
      - type: `['boolean', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `region` *required*: `string`
      - type: `string`
    - `secret_key` *required*: `string`
      - type: `string`
- responses:
  - `200`: Connection test result
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Human-readable message (success confirmation or error detail).
        - type: `string`
      - `ok` *required*: `boolean`
        - description: Whether the connection and credentials worked.
        - type: `boolean`
      - `warnings`: `array<string>`
        - description: Caveats of a successful test, e.g. a host-loopback endpoint that
        - type: `array<string>`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/s3-sources/{id}`

- operationId: `get_s3_source`
- summary: Read one S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: S3 source details
    - `application/json`:
      - type: `object (12 properties)`
      - `access_key_id` *required*: `string`
        - type: `string`
      - `bucket_name` *required*: `string`
        - type: `string`
      - `bucket_path` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `endpoint`: `['string', 'null']`
        - type: `['string', 'null']`
      - `force_path_style` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `secret_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/backups/s3-sources/{id}`

- operationId: `update_s3_source`
- summary: Update one S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `access_key_id`: `['string', 'null']`
      - description: Optional new access key ID
      - type: `['string', 'null']`
    - `bucket_name`: `['string', 'null']`
      - description: Optional new bucket name
      - type: `['string', 'null']`
    - `bucket_path`: `['string', 'null']`
      - description: Optional new bucket path
      - type: `['string', 'null']`
    - `endpoint`: `['string', 'null']`
      - description: Optional new endpoint URL for a self-hosted S3 service
      - type: `['string', 'null']`
    - `force_path_style`: `['boolean', 'null']`
      - description: Optional new path-style addressing setting
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - description: Optional new name for the source
      - type: `['string', 'null']`
    - `region`: `['string', 'null']`
      - description: Optional new region
      - type: `['string', 'null']`
    - `secret_key`: `['string', 'null']`
      - description: Optional new secret key
      - type: `['string', 'null']`
- responses:
  - `200`: S3 source updated
    - `application/json`:
      - type: `object (12 properties)`
      - `access_key_id` *required*: `string`
        - type: `string`
      - `bucket_name` *required*: `string`
        - type: `string`
      - `bucket_path` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `endpoint`: `['string', 'null']`
        - type: `['string', 'null']`
      - `force_path_style` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `secret_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/backups/s3-sources/{id}`

- operationId: `delete_s3_source`
- summary: Delete one S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: S3 source deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/s3-sources/{id}/backups`

- operationId: `list_source_backups`
- summary: List the backups stored in one S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `include_s3_scan` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Backups in the source
    - `application/json`:
      - type: `object (2 properties)`
      - `backups` *required*: `array<object (13 properties)>`
        - description: List of backups in the source
        - type: `array<object (13 properties)>`
      - `last_updated` *required*: `string`
        - description: When the index was last updated
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/s3-sources/{id}/run`

- operationId: `run_backup_for_source`
- summary: Enqueue a control-plane backup into one S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `backup_type` *required*: `string`
      - description: Type of backup to perform
      - type: `string`
- responses:
  - `202`: Backup enqueued for async execution
    - `application/json`:
      - type: `object (25 properties)`
      - `attempts`: `['integer', 'null']`
        - description: How many times this job has been claimed and run. `null` for legacy
        - type: `['integer', 'null']`
      - `backup_type` *required*: `string`
        - type: `string`
      - `backup_uuid` *required*: `string`
        - description: The backup's UUID (`backups.backup_id`), shown as its label and used
        - type: `string`
      - `checksum`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `compression_type` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `current_step`: `['string', 'null']`
        - description: Name of the engine step currently executing (e.g., `"walg_push"`).
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `file_count`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - description: Row id of the backup (`backups.id`): the `{id}` of every
        - type: `integer`
      - `live_size_bytes`: `['integer', 'null']`
        - description: Best-effort partial size while a backup is still running, computed
        - type: `['integer', 'null']`
      - `managed_service`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `max_attempts`: `['integer', 'null']`
        - description: Maximum attempts before the job is permanently failed. `null` for
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Resolved wall-clock timeout for this backup job (seconds). `null` for
        - type: `['integer', 'null']`
      - `metadata` *required*: `any`
        - type: `any`
      - `name` *required*: `string`
        - type: `string`
      - `s3_location` *required*: `string`
        - type: `string`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `size_bytes`: `['integer', 'null']`
        - description: Final size of the backup once completed. Null while running.
        - type: `['integer', 'null']`
      - `started_at` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/s3-sources/{id}/set-default`

- operationId: `set_default_s3_source`
- summary: Mark one S3 source as the organization default.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: S3 source marked as default
    - `application/json`:
      - type: `object (12 properties)`
      - `access_key_id` *required*: `string`
        - type: `string`
      - `bucket_name` *required*: `string`
        - type: `string`
      - `bucket_path` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `endpoint`: `['string', 'null']`
        - type: `['string', 'null']`
      - `force_path_style` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `secret_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/s3-sources/{id}/test`

- operationId: `test_s3_source_connection`
- summary: Test connectivity to a stored S3 source.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connection test result
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Human-readable message (success confirmation or error detail).
        - type: `string`
      - `ok` *required*: `boolean`
        - description: Whether the connection and credentials worked.
        - type: `boolean`
      - `warnings`: `array<string>`
        - description: Caveats of a successful test, e.g. a host-loopback endpoint that
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: S3 source not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/schedule-runs/{id}/cancel`

- operationId: `cancel_schedule_run`
- summary: Cancel every non-terminal child backup of one schedule run.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cancel processed (idempotent)
    - `application/json`:
      - type: `object (1 properties)`
      - `cancelled` *required*: `integer`
        - description: Number of rows that were actually flipped to `failed`. `0` is a valid
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule run not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/schedules`

- operationId: `list_backup_schedules`
- summary: List an organization's backup schedules.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of backup schedules
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/schedules`

- operationId: `create_backup_schedule`
- summary: Create a backup schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `backup_type` *required*: `string`
      - type: `string`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `enabled` *required*: `boolean`
      - type: `boolean`
    - `include_control_plane`: `['boolean', 'null']`
      - description: When `true` (default), every run also produces a `control_plane`
      - type: `['boolean', 'null']`
    - `max_runtime_secs`: `['integer', 'null']`
      - description: Optional wall-clock timeout override for jobs created by this schedule
      - type: `['integer', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `retention_period` *required*: `integer`
      - type: `integer`
    - `s3_source_id`: `['integer', 'null']`
      - description: Optional S3 source. If omitted, the current default S3 source is used.
      - type: `['integer', 'null']`
    - `schedule_expression` *required*: `string`
      - type: `string`
    - `service_ids`: `['array', 'null']`
      - description: Services to attach in the same transaction as the create. With
      - type: `['array', 'null']`
    - `tags` *required*: `array<string>`
      - type: `array<string>`
    - `target_all_services`: `['boolean', 'null']`
      - description: When `true` (default), the schedule backs up every managed service
      - type: `['boolean', 'null']`
- responses:
  - `201`: Backup schedule created
    - `application/json`:
      - type: `object (16 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_control_plane` *required*: `boolean`
        - description: When `true`, every run also produces a `control_plane` backup
        - type: `boolean`
      - `last_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Per-schedule wall-clock timeout override for backup jobs (seconds).
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `next_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `retention_period` *required*: `integer`
        - type: `integer`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_expression` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
      - `target_all_services` *required*: `boolean`
        - description: When `true`, the schedule auto-includes every managed service on
        - type: `boolean`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/schedules/{id}`

- operationId: `get_backup_schedule`
- summary: Read one backup schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Backup schedule details
    - `application/json`:
      - type: `object (16 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_control_plane` *required*: `boolean`
        - description: When `true`, every run also produces a `control_plane` backup
        - type: `boolean`
      - `last_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Per-schedule wall-clock timeout override for backup jobs (seconds).
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `next_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `retention_period` *required*: `integer`
        - type: `integer`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_expression` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
      - `target_all_services` *required*: `boolean`
        - description: When `true`, the schedule auto-includes every managed service on
        - type: `boolean`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/backups/schedules/{id}`

- operationId: `update_backup_schedule`
- summary: Update one backup schedule (partial).
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `description`: `['string', 'null']`
      - description: New human-readable description. Pass an empty string `""` to clear.
      - type: `['string', 'null']`
    - `enabled`: `['boolean', 'null']`
      - description: Enable or disable the schedule. Skipped when `None`.
      - type: `['boolean', 'null']`
    - `include_control_plane`: `['boolean', 'null']`
      - description: Toggle whether the control-plane backup is produced on every run.
      - type: `['boolean', 'null']`
    - `max_runtime_secs`: `['integer', 'null']`
      - description: Per-schedule wall-clock timeout override (seconds).
      - type: `['integer', 'null']`
    - `name`: `['string', 'null']`
      - description: New schedule name. Skipped when `None`. Must not be empty if provided.
      - type: `['string', 'null']`
    - `retention_period`: `['integer', 'null']`
      - description: Days to retain backups produced by this schedule. Must be >= 1.
      - type: `['integer', 'null']`
    - `schedule_expression`: `['string', 'null']`
      - description: New cron expression. When changed, `next_run` is recomputed.
      - type: `['string', 'null']`
    - `tags`: `['array', 'null']`
      - description: Replace the full tag list. Skipped when `None`.
      - type: `['array', 'null']`
    - `target_all_services`: `['boolean', 'null']`
      - description: Toggle between "back up every database" (`true`) and "back up only
      - type: `['boolean', 'null']`
- responses:
  - `200`: Schedule updated
    - `application/json`:
      - type: `object (16 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_control_plane` *required*: `boolean`
        - description: When `true`, every run also produces a `control_plane` backup
        - type: `boolean`
      - `last_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Per-schedule wall-clock timeout override for backup jobs (seconds).
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `next_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `retention_period` *required*: `integer`
        - type: `integer`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_expression` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
      - `target_all_services` *required*: `boolean`
        - description: When `true`, the schedule auto-includes every managed service on
        - type: `boolean`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/backups/schedules/{id}`

- operationId: `delete_backup_schedule`
- summary: Delete one backup schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Backup schedule deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/schedules/{id}/backups`

- operationId: `list_backups_for_schedule`
- summary: List the backups produced by one schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Backups for the schedule
    - `application/json`:
      - type: `array<object (25 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/backups/schedules/{id}/disable`

- operationId: `disable_backup_schedule`
- summary: Disable one backup schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Backup schedule disabled
    - `application/json`:
      - type: `object (16 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_control_plane` *required*: `boolean`
        - description: When `true`, every run also produces a `control_plane` backup
        - type: `boolean`
      - `last_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Per-schedule wall-clock timeout override for backup jobs (seconds).
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `next_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `retention_period` *required*: `integer`
        - type: `integer`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_expression` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
      - `target_all_services` *required*: `boolean`
        - description: When `true`, the schedule auto-includes every managed service on
        - type: `boolean`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/backups/schedules/{id}/enable`

- operationId: `enable_backup_schedule`
- summary: Enable one backup schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Backup schedule enabled
    - `application/json`:
      - type: `object (16 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_control_plane` *required*: `boolean`
        - description: When `true`, every run also produces a `control_plane` backup
        - type: `boolean`
      - `last_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Per-schedule wall-clock timeout override for backup jobs (seconds).
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `next_run`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `retention_period` *required*: `integer`
        - type: `integer`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_expression` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
      - `target_all_services` *required*: `boolean`
        - description: When `true`, the schedule auto-includes every managed service on
        - type: `boolean`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/schedules/{id}/run`

- operationId: `run_schedule_now`
- summary: Fan out a run for one schedule immediately.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Fan-out run enqueued
    - `application/json`:
      - type: `object (2 properties)`
      - `jobs` *required*: `array<object (4 properties)>`
        - description: All jobs that were enqueued in this fan-out.
        - type: `array<object (4 properties)>`
      - `schedule_run_id` *required*: `integer`
        - description: The `schedule_runs.id` of the newly created run.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `409`: Run already in flight or schedule disabled
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/schedules/{id}/runs`

- operationId: `list_schedule_runs`
- summary: Paginated run history for one schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Paginated run history
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - description: Current page (1-based).
        - type: `integer`
      - `page_size` *required*: `integer`
        - description: Number of items per page.
        - type: `integer`
      - `runs` *required*: `array<object (11 properties)>`
        - description: Run summaries, newest first. Includes synthetic single-job rows for
        - type: `array<object (11 properties)>`
      - `total` *required*: `integer`
        - description: Total number of run entries across all pages.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/schedules/{id}/services`

- operationId: `list_schedule_services`
- summary: List the managed services attached to one schedule.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Services attached to this schedule
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/schedules/{id}/services`

- operationId: `attach_schedule_services`
- summary: Attach managed services to one schedule. Idempotent.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `service_ids` *required*: `array<integer>`
      - description: Managed service ids to attach. Duplicates are de-duplicated server-side.
      - type: `array<integer>`
- responses:
  - `200`: Services attached
    - `application/json`:
      - type: `object (2 properties)`
      - `inserted` *required*: `integer`
        - description: Number of rows actually inserted (excludes rows skipped by
        - type: `integer`
      - `total_attached` *required*: `integer`
        - description: Total number of services now attached to the schedule.
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/backups/schedules/{id}/services/{service_id}`

- operationId: `detach_schedule_service`
- summary: Detach one managed service from one schedule. Idempotent.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Service detached (or was not attached)
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Schedule not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/services/{id}/backups`

- operationId: `list_service_backups`
- summary: Paginated backups for one managed service.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Paginated backups for this service
    - `application/json`:
      - type: `object (4 properties)`
      - `backups` *required*: `array<object (14 properties)>`
        - description: Backups belonging to this service, newest first.
        - type: `array<object (14 properties)>`
      - `page` *required*: `integer`
        - description: Current page (1-based).
        - type: `integer`
      - `page_size` *required*: `integer`
        - description: Number of items per page.
        - type: `integer`
      - `total` *required*: `integer`
        - description: Total number of backups for this service across all pages.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Service not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/services/{id}/run`

- operationId: `run_service_backup`
- summary: Enqueue a backup for one managed service.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `backup_type`: `['string', 'null']`
      - description: Type of backup to perform (e.g., "full", "incremental")
      - type: `['string', 'null']`
    - `s3_source_id`: `['integer', 'null']`
      - description: ID of the S3 source to store the backup. If omitted, the current default S3 source is used.
      - type: `['integer', 'null']`
- responses:
  - `202`: Backup enqueued for async execution
    - `application/json`:
      - type: `object (15 properties)`
      - `backup_type` *required*: `string`
        - type: `string`
      - `checksum`: `['string', 'null']`
        - type: `['string', 'null']`
      - `compression_type` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - description: Row id of the backup (`backups.id`).
        - type: `integer`
      - `managed_service_backup_id` *required*: `integer`
        - description: Row id of the per-service child (`managed_service_backups.id`).
        - type: `integer`
      - `metadata` *required*: `any`
        - type: `any`
      - `s3_location` *required*: `string`
        - type: `string`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `started_at` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Service or S3 source not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/services/{service_id}/schedules`

- operationId: `list_service_schedules`
- summary: List the schedules that target one managed service.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Schedules backing up this service
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Service not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/{id}`

- operationId: `get_backup`
- summary: Read one backup by its row id.
- description: KI-220: the `{id}` is the backup's row id, as on `…/backups/{id}/cancel`
and `…/backups/{id}/children` and as the `id` the run and list answers
carry. The UUID (`backup_uuid` in every answer) is not an id here; a
non-integer `{id}` is a 400.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Backup details
    - `application/json`:
      - type: `object (25 properties)`
      - `attempts`: `['integer', 'null']`
        - description: How many times this job has been claimed and run. `null` for legacy
        - type: `['integer', 'null']`
      - `backup_type` *required*: `string`
        - type: `string`
      - `backup_uuid` *required*: `string`
        - description: The backup's UUID (`backups.backup_id`), shown as its label and used
        - type: `string`
      - `checksum`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `compression_type` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `current_step`: `['string', 'null']`
        - description: Name of the engine step currently executing (e.g., `"walg_push"`).
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `file_count`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - description: Row id of the backup (`backups.id`): the `{id}` of every
        - type: `integer`
      - `live_size_bytes`: `['integer', 'null']`
        - description: Best-effort partial size while a backup is still running, computed
        - type: `['integer', 'null']`
      - `managed_service`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `max_attempts`: `['integer', 'null']`
        - description: Maximum attempts before the job is permanently failed. `null` for
        - type: `['integer', 'null']`
      - `max_runtime_secs`: `['integer', 'null']`
        - description: Resolved wall-clock timeout for this backup job (seconds). `null` for
        - type: `['integer', 'null']`
      - `metadata` *required*: `any`
        - type: `any`
      - `name` *required*: `string`
        - type: `string`
      - `s3_location` *required*: `string`
        - type: `string`
      - `s3_source_id` *required*: `integer`
        - type: `integer`
      - `schedule_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `size_bytes`: `['integer', 'null']`
        - description: Final size of the backup once completed. Null while running.
        - type: `['integer', 'null']`
      - `started_at` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - type: `string`
      - `tags` *required*: `array<string>`
        - type: `array<string>`
  - `400`: The id is not an integer
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Backup not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/backups/{id}/cancel`

- operationId: `cancel_backup`
- summary: Cancel one in-flight backup.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cancel processed (idempotent)
    - `application/json`:
      - type: `object (1 properties)`
      - `cancelled` *required*: `integer`
        - description: Number of rows that were actually flipped to `failed`. `0` is a valid
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Backup not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/backups/{id}/children`

- operationId: `list_backup_children`
- summary: List the managed-service child backups of one parent backup.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Child backup list (may be empty)
    - `application/json`:
      - type: `object (1 properties)`
      - `children` *required*: `array<object (12 properties)>`
        - description: Zero or more child backup entries ordered by `managed_service_backups.id` ASC.
        - type: `array<object (12 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Parent backup not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/billing/customers`

- operationId: `listBillingCustomers`
- summary: One page of the organization's customers, oldest first.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `q` (query): `string`
  - `status` (query): `string`
  - `limit` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: One page of customers
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `next_cursor`: `['string', 'null']`
        - description: `null` at the end of the list. Present only when another row is known to
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: Malformed cursor

### `POST /v1/orgs/{org_slug}/billing/customers`

- operationId: `createBillingCustomer`
- summary: Register one of the organization's own `SaaS` accounts.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `currency` *required*: `string`
      - description: `ISO-4217`, lowercase. Must match the plan of any subscription.
      - type: `string`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `external_id` *required*: `string`
      - description: The organization's own identifier. Unique within the organization; a
      - type: `string`
    - `metadata`: `['object', 'null']`
      - type: `['object', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `project_id`: `['integer', 'null']`
      - description: The `ConusAI` project dedicated to this customer, whose platform usage is
      - type: `['integer', 'null']`
    - `stripe_customer_id`: `['string', 'null']`
      - description: This customer's id in the organization's own Stripe account (§15).
      - type: `['string', 'null']`
- responses:
  - `201`: Customer created
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `currency` *required*: `string`
        - description: `ISO-4217`, lowercase.
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `external_id` *required*: `string`
        - description: The organization's own identifier for this account.
        - type: `string`
      - `id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `metadata` *required*: `object`
        - type: `object`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - description: The dedicated `ConusAI` project whose infrastructure usage is attributed
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - description: Lifecycle of an organization's customer.
        - type: `string`
      - `stripe_customer_id`: `['string', 'null']`
        - description: This customer's mirror in the organization's **own** Stripe account
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `409`: external_id already used in this organization
  - `422`: Validation failed

### `GET /v1/orgs/{org_slug}/billing/customers/{customer_id}`

- operationId: `getBillingCustomer`
- summary: One customer by the id `ConusAI` minted.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The customer
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `currency` *required*: `string`
        - description: `ISO-4217`, lowercase.
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `external_id` *required*: `string`
        - description: The organization's own identifier for this account.
        - type: `string`
      - `id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `metadata` *required*: `object`
        - type: `object`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - description: The dedicated `ConusAI` project whose infrastructure usage is attributed
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - description: Lifecycle of an organization's customer.
        - type: `string`
      - `stripe_customer_id`: `['string', 'null']`
        - description: This customer's mirror in the organization's **own** Stripe account
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer in this organization

### `PATCH /v1/orgs/{org_slug}/billing/customers/{customer_id}`

- operationId: `updateBillingCustomer`
- summary: Patch a customer's name, email or metadata.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `metadata`: `['object', 'null']`
      - type: `['object', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `project_id`: `['integer', 'null']`
      - description: Absent leaves the link alone; `null` clears it; a number sets it (§14).
      - type: `['integer', 'null']`
    - `stripe_customer_id`: `['string', 'null']`
      - description: Absent leaves it alone; `null` clears it; a string sets it (§15).
      - type: `['string', 'null']`
- responses:
  - `200`: The updated customer
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `currency` *required*: `string`
        - description: `ISO-4217`, lowercase.
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `external_id` *required*: `string`
        - description: The organization's own identifier for this account.
        - type: `string`
      - `id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `metadata` *required*: `object`
        - type: `object`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - description: The dedicated `ConusAI` project whose infrastructure usage is attributed
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - description: Lifecycle of an organization's customer.
        - type: `string`
      - `stripe_customer_id`: `['string', 'null']`
        - description: This customer's mirror in the organization's **own** Stripe account
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer in this organization
  - `422`: Validation failed

### `GET /v1/orgs/{org_slug}/billing/customers/{customer_id}/subscriptions`

- operationId: `listCustomerSubscriptions`
- summary: Every subscription of one customer, newest first, cancelled ones included.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The customer's subscriptions
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer in this organization

### `GET /v1/orgs/{org_slug}/billing/customers/{customer_id}/usage`

- operationId: `getCustomerUsage`
- summary: One customer's usage over a window, bucketed by hour or day.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `meter` (query): `string`
  - `granularity` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Usage per meter, per bucket
    - `application/json`:
      - type: `object (5 properties)`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `from` *required*: `string`
        - type: `string`
      - `granularity` *required*: `string`
        - description: Bucket width of `GET /billing/customers/{id}/usage`.
        - type: `string`
      - `series` *required*: `array<object (7 properties)>`
        - description: One entry per meter with usage in the window, ordered by meter key.
        - type: `array<object (7 properties)>`
      - `to` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer in this organization
  - `422`: `from` is not before `to`, or the meter key is malformed

### `GET /v1/orgs/{org_slug}/billing/customers/{customer_id}/usage/current`

- operationId: `getCustomerCurrentPeriodUsage`
- summary: The open period's totals per meter and the rated preview of its invoice.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Open-period totals and preview; the period fields are null when the customer has no active subscription
    - `application/json`:
      - type: `object (10 properties)`
      - `currency`: `['string', 'null']`
        - type: `['string', 'null']`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `period_end`: `['string', 'null']`
        - type: `['string', 'null']`
      - `period_start`: `['string', 'null']`
        - type: `['string', 'null']`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preview_lines`: `['array', 'null']`
        - description: `null` when there is no subscription to rate.
        - type: `['array', 'null']`
      - `preview_subtotal_minor`: `['integer', 'null']`
        - description: Sum of `preview_lines`, integer minor units; `null` with them.
        - type: `['integer', 'null']`
      - `subscription_id`: `string | null`
        - type: `string | null`
      - `totals` *required*: `array<object (6 properties)>`
        - description: Every meter with usage in the period, priced or not.
        - type: `array<object (6 properties)>`
      - `usage_through`: `['string', 'null']`
        - description: Up to which instant usage has actually been counted: the end of the last
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer in this organization
  - `422`: The plan's price book cannot be rated

### `POST /v1/orgs/{org_slug}/billing/events`

- operationId: `ingestBillingEvents`
- summary: Record a batch of usage events.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `events` *required*: `array<object (6 properties)>`
      - description: At most [`MAX_BATCH_EVENTS`]; the body is additionally capped at 1 MiB
      - type: `array<object (6 properties)>`
- responses:
  - `202`: The batch was processed; per-event outcomes are in the body
    - `application/json`:
      - type: `object (3 properties)`
      - `accepted` *required*: `integer`
        - description: Events stored by this call.
        - type: `integer`
      - `duplicates` *required*: `integer`
        - description: Events whose `(organization, idempotency_key)` was already present —
        - type: `integer`
      - `rejected` *required*: `array<object (2 properties)>`
        - description: Events that were not stored, with the reason for each.
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `413`: Body over 1 MiB, or more than 1000 events
  - `422`: Every event in the batch was rejected
    - `application/json`:
      - type: `object (3 properties)`
      - `accepted` *required*: `integer`
        - description: Events stored by this call.
        - type: `integer`
      - `duplicates` *required*: `integer`
        - description: Events whose `(organization, idempotency_key)` was already present —
        - type: `integer`
      - `rejected` *required*: `array<object (2 properties)>`
        - description: Events that were not stored, with the reason for each.
        - type: `array<object (2 properties)>`

### `GET /v1/orgs/{org_slug}/billing/invoices`

- operationId: `listCustomerInvoices`
- summary: One page of the organization's invoices, newest first.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `customer_id` (query): `string`
  - `status` (query): `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `limit` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: One page of invoices
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
      - `next_cursor`: `['string', 'null']`
        - description: Pass back as `?cursor=`; `null` at the end of the list.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: Malformed cursor

### `GET /v1/orgs/{org_slug}/billing/invoices/{invoice_id}`

- operationId: `getCustomerInvoice`
- summary: One invoice with its lines and its customer.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invoice_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The invoice and its lines
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such invoice in this organization

### `GET /v1/orgs/{org_slug}/billing/invoices/{invoice_id}/lines.csv`

- operationId: `exportCustomerInvoiceLinesCsv`
- summary: The invoice's lines as `CSV`.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invoice_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: RFC 4180 CSV, one row per line, in invoice order
    - `text/csv`:
      - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such invoice in this organization

### `POST /v1/orgs/{org_slug}/billing/invoices/{invoice_id}/mark-paid`

- operationId: `markCustomerInvoicePaid`
- summary: Record that an invoice was paid.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invoice_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `paid_at`: `['string', 'null']`
      - description: When payment was received; defaults to now. Never in the future.
      - type: `['string', 'null']`
- responses:
  - `200`: The invoice, now paid
    - `application/json`:
      - type: `object (14 properties)`
      - `currency` *required*: `string`
        - type: `string`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `id` *required*: `string`
        - description: An issued statement for one subscription period (`customer_invoices.id`).
        - type: `string`
      - `issued_at` *required*: `string`
        - type: `string`
      - `number` *required*: `string`
        - description: `INV-2026-000042`. Dense and sequential per organization per year.
        - type: `string`
      - `paid_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `period_end` *required*: `string`
        - type: `string`
      - `period_start` *required*: `string`
        - description: Half-open: `[period_start, period_end)`.
        - type: `string`
      - `seller`: `object (9 properties) | null`
        - type: `object (9 properties) | null`
      - `status` *required*: `string`
        - description: Lifecycle of an issued invoice.
        - type: `string`
      - `subscription_id` *required*: `string`
        - description: A customer's subscription to a plan (`billing_subscriptions.id`).
        - type: `string`
      - `subtotal_minor` *required*: `integer`
        - description: Integer minor units — the sum of the lines.
        - type: `integer`
      - `total_minor` *required*: `integer`
        - description: Equal to [`Self::subtotal_minor`] until tax exists (decision D13).
        - type: `integer`
      - `voided_at`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such invoice in this organization
  - `409`: The invoice is void
  - `422`: paid_at is in the future

### `POST /v1/orgs/{org_slug}/billing/invoices/{invoice_id}/push-to-stripe`

- operationId: `pushCustomerInvoiceToStripe`
- summary: Mirror an issued invoice into the organization's own Stripe account (§15).
- description: The manual half of the push: the background pass gives up after five
failures, and this is how an operator who has fixed the cause — a rotated
key, a Stripe customer that now exists — asks for the invoice to be pushed
now. It is therefore not subject to that ceiling.

Safe to repeat. An invoice that is already mirrored answers `already_pushed`
and calls nothing, and an invoice whose draft exists but was never finalized
is finalized rather than re-created — Stripe's own idempotency key covers the
window in between.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invoice_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: What the push did
    - `application/json`:
      - type: `object (8 properties)`
      - `attempts` *required*: `integer`
        - description: How many push attempts have **failed**. The background pass gives up at
        - type: `integer`
      - `invoice_id` *required*: `string`
        - description: An issued statement for one subscription period (`customer_invoices.id`).
        - type: `string`
      - `last_error`: `['string', 'null']`
        - description: Why the last attempt failed, if one did. Cleared by a success.
        - type: `['string', 'null']`
      - `number` *required*: `string`
        - description: The `ConusAI` invoice number, so a log line or a toast identifies the
        - type: `string`
      - `outcome` *required*: `string`
        - description: What a push attempt did.
        - type: `string`
      - `pushed_at`: `['string', 'null']`
        - description: When the mirror was finalized.
        - type: `['string', 'null']`
      - `reason`: `['string', 'null']`
        - description: Why nothing was attempted, when the outcome is `skipped`.
        - type: `['string', 'null']`
      - `stripe_invoice_id`: `['string', 'null']`
        - description: The Stripe invoice this one is mirrored by, once it exists.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such invoice in this organization
  - `422`: The Stripe sync is off, the customer has no stripe_customer_id, or the invoice is not issued
  - `502`: Stripe refused; the ConusAI invoice is unaffected

### `POST /v1/orgs/{org_slug}/billing/invoices/{invoice_id}/void`

- operationId: `voidCustomerInvoice`
- summary: Withdraw an invoice.
- description: The reason is required and lands in the audit log rather than on the row:
the invoice is the statement that was sent, and a statement that grows a
free-text field after the fact is a statement that changed (invariant I6).
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invoice_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `reason` *required*: `string`
      - type: `string`
- responses:
  - `200`: The invoice, now void
    - `application/json`:
      - type: `object (14 properties)`
      - `currency` *required*: `string`
        - type: `string`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `id` *required*: `string`
        - description: An issued statement for one subscription period (`customer_invoices.id`).
        - type: `string`
      - `issued_at` *required*: `string`
        - type: `string`
      - `number` *required*: `string`
        - description: `INV-2026-000042`. Dense and sequential per organization per year.
        - type: `string`
      - `paid_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `period_end` *required*: `string`
        - type: `string`
      - `period_start` *required*: `string`
        - description: Half-open: `[period_start, period_end)`.
        - type: `string`
      - `seller`: `object (9 properties) | null`
        - type: `object (9 properties) | null`
      - `status` *required*: `string`
        - description: Lifecycle of an issued invoice.
        - type: `string`
      - `subscription_id` *required*: `string`
        - description: A customer's subscription to a plan (`billing_subscriptions.id`).
        - type: `string`
      - `subtotal_minor` *required*: `integer`
        - description: Integer minor units — the sum of the lines.
        - type: `integer`
      - `total_minor` *required*: `integer`
        - description: Equal to [`Self::subtotal_minor`] until tax exists (decision D13).
        - type: `integer`
      - `voided_at`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such invoice in this organization
  - `409`: The invoice has been paid
  - `422`: The reason is empty

### `GET /v1/orgs/{org_slug}/billing/meters`

- operationId: `listBillingMeters`
- summary: Every meter the organization has defined.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `include_archived` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: The organization's meters
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/billing/meters`

- operationId: `createBillingMeter`
- summary: Define a quantity to bill on.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `aggregation` *required*: `string`
      - description: How a meter's events combine into an hourly quantity, and how those
      - type: `string`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `display_name` *required*: `string`
      - type: `string`
    - `key` *required*: `string`
      - description: `^[a-z][a-z0-9_.]{1,63}$`. The `infra.` prefix is reserved for the
      - type: `string`
    - `unit` *required*: `string`
      - type: `string`
- responses:
  - `201`: Meter created
    - `application/json`:
      - type: `object (9 properties)`
      - `aggregation` *required*: `string`
        - description: How a meter's events combine into an hourly quantity, and how those
        - type: `string`
      - `archived_at`: `['string', 'null']`
        - description: `null` while the meter still accepts events.
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `display_name` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - description: An organization-defined metered quantity (`billing_meters.id`).
        - type: `string`
      - `key` *required*: `string`
        - type: `string`
      - `unit` *required*: `string`
        - description: Display only; never used in arithmetic.
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `409`: A meter with that key already exists
  - `422`: Malformed key, or the reserved 'infra.' prefix

### `PATCH /v1/orgs/{org_slug}/billing/meters/{meter_id}`

- operationId: `updateBillingMeter`
- summary: Patch a meter's presentation.
- description: `key` and `aggregation` are not in [`UpdateMeterInput`] and there is no route
that changes them: the key is what every ingested event names, and the
aggregation is the rule every closed hour was computed under.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `meter_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `display_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `unit`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: The updated meter
    - `application/json`:
      - type: `object (9 properties)`
      - `aggregation` *required*: `string`
        - description: How a meter's events combine into an hourly quantity, and how those
        - type: `string`
      - `archived_at`: `['string', 'null']`
        - description: `null` while the meter still accepts events.
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `display_name` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - description: An organization-defined metered quantity (`billing_meters.id`).
        - type: `string`
      - `key` *required*: `string`
        - type: `string`
      - `unit` *required*: `string`
        - description: Display only; never used in arithmetic.
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such meter in this organization
  - `422`: Validation failed

### `POST /v1/orgs/{org_slug}/billing/meters/{meter_id}/archive`

- operationId: `archiveBillingMeter`
- summary: Stop a meter accepting events. Its history still rates.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `meter_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Meter archived
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such meter in this organization
  - `409`: An open plan price still references the meter

### `GET /v1/orgs/{org_slug}/billing/plans`

- operationId: `listBillingPlans`
- summary: The organization's plans with the price that applies now.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `include_archived` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Plans with their currently open prices
    - `application/json`:
      - type: `array<any>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/billing/plans`

- operationId: `createBillingPlan`
- summary: Create a plan together with its initial prices.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `base_fee_minor`: `integer`
      - type: `integer`
    - `currency` *required*: `string`
      - type: `string`
    - `interval`: `string | null`
      - type: `string | null`
    - `key` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `prices`: `array<object (7 properties)>`
      - description: Written in the same transaction as the plan, so a plan never exists in a
      - type: `array<object (7 properties)>`
- responses:
  - `201`: Plan created with its prices
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `409`: A plan with that key already exists
  - `422`: Unknown meter, unordered tiers, or price fields that do not match the model

### `GET /v1/orgs/{org_slug}/billing/plans/{plan_id}`

- operationId: `getBillingPlan`
- summary: One plan with the **full** price history, newest first.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The plan and every price it has ever had
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such plan in this organization

### `POST /v1/orgs/{org_slug}/billing/plans/{plan_id}/archive`

- operationId: `archiveBillingPlan`
- summary: Retire a plan. Its issued invoices and its price history stay.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Plan archived
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such plan in this organization
  - `409`: Active subscriptions still reference the plan

### `PUT /v1/orgs/{org_slug}/billing/plans/{plan_id}/prices/{meter_id}`

- operationId: `setBillingPlanPrice`
- summary: Set what one meter costs in one plan, from an instant onwards.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
  - `meter_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `effective_from`: `['string', 'null']`
      - description: When the new price starts applying; defaults to now. The open row is
      - type: `['string', 'null']`
    - `included_quantity`: `['string', 'null']`
      - type: `['string', 'null']`
    - `model` *required*: `string`
      - description: How a plan prices one meter (decision D5 for the tiered semantics).
      - type: `string`
    - `package_price_minor`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `package_size`: `['string', 'null']`
      - type: `['string', 'null']`
    - `tiers`: `['array', 'null']`
      - type: `['array', 'null']`
    - `unit_price_minor`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: The new price row; the previous one is now closed
    - `application/json`:
      - type: `object (11 properties)`
      - `effective_from` *required*: `string`
        - type: `string`
      - `effective_until`: `['string', 'null']`
        - description: `null` while this is the open row for its `(plan, meter)`.
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - description: One effective-dated price of one meter inside one plan
        - type: `string`
      - `included_quantity` *required*: `string`
        - type: `string`
      - `meter_id` *required*: `string`
        - description: An organization-defined metered quantity (`billing_meters.id`).
        - type: `string`
      - `meter_key` *required*: `string`
        - description: Carried alongside the id so a caller does not have to join the meter
        - type: `string`
      - `model` *required*: `string`
        - description: How a plan prices one meter (decision D5 for the tiered semantics).
        - type: `string`
      - `package_price_minor`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `package_size`: `['string', 'null']`
        - type: `['string', 'null']`
      - `tiers`: `['array', 'null']`
        - type: `['array', 'null']`
      - `unit_price_minor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such plan or meter in this organization
  - `409`: The plan is archived
  - `422`: Price fields do not match the model, tiers are unordered, or effective_from is not after the price it replaces

### `GET /v1/orgs/{org_slug}/billing/seller-profile`

- operationId: `getCustomerBillingSellerProfile`
- summary: This organization's seller profile.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The seller profile
    - `application/json`:
      - type: `object (9 properties)`
      - `address_lines` *required*: `array<string>`
        - description: Postal address, one line per element, at most six.
        - type: `array<string>`
      - `company_registration_id`: `['string', 'null']`
        - description: Company register number, if any.
        - type: `['string', 'null']`
      - `country_code` *required*: `string`
        - description: ISO 3166-1 alpha-2.
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `footer_note`: `['string', 'null']`
        - description: Free text printed at the foot of each invoice.
        - type: `['string', 'null']`
      - `legal_name` *required*: `string`
        - description: The registered name the invoices are issued under.
        - type: `string`
      - `phone`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `vat_id`: `['string', 'null']`
        - description: VAT identification number, if the organization is registered.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found, or no seller profile saved yet

### `PUT /v1/orgs/{org_slug}/billing/seller-profile`

- operationId: `updateCustomerBillingSellerProfile`
- summary: Replace the organization's seller profile, creating it on first save.
- description: Invoices issued after this call carry the new details. Invoices already
issued keep the details they were issued under.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `address_lines`: `array<string>`
      - description: Up to six lines; blank lines are dropped.
      - type: `array<string>`
    - `company_registration_id`: `['string', 'null']`
      - description: At most 64 characters.
      - type: `['string', 'null']`
    - `country_code` *required*: `string`
      - description: Two letters, upper case once trimmed.
      - type: `string`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `footer_note`: `['string', 'null']`
      - description: At most 1000 characters.
      - type: `['string', 'null']`
    - `legal_name` *required*: `string`
      - description: 1..=200 characters.
      - type: `string`
    - `phone`: `['string', 'null']`
      - type: `['string', 'null']`
    - `vat_id`: `['string', 'null']`
      - description: 4..=20 characters when given.
      - type: `['string', 'null']`
- responses:
  - `200`: The profile after the change
    - `application/json`:
      - type: `object (9 properties)`
      - `address_lines` *required*: `array<string>`
        - description: Postal address, one line per element, at most six.
        - type: `array<string>`
      - `company_registration_id`: `['string', 'null']`
        - description: Company register number, if any.
        - type: `['string', 'null']`
      - `country_code` *required*: `string`
        - description: ISO 3166-1 alpha-2.
        - type: `string`
      - `email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `footer_note`: `['string', 'null']`
        - description: Free text printed at the foot of each invoice.
        - type: `['string', 'null']`
      - `legal_name` *required*: `string`
        - description: The registered name the invoices are issued under.
        - type: `string`
      - `phone`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `vat_id`: `['string', 'null']`
        - description: VAT identification number, if the organization is registered.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: A field is outside the range the invoices can carry

### `GET /v1/orgs/{org_slug}/billing/settings`

- operationId: `getCustomerBillingSettings`
- summary: This organization's customer-billing settings, or the defaults.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The settings, or the shipped defaults
    - `application/json`:
      - type: `object (3 properties)`
      - `invoice_prefix` *required*: `string`
        - description: The `INV` in `INV-2026-000042`.
        - type: `string`
      - `stripe_sync_enabled` *required*: `boolean`
        - description: Whether issued invoices are mirrored into the organization's own Stripe
        - type: `boolean`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `PUT /v1/orgs/{org_slug}/billing/settings`

- operationId: `updateCustomerBillingSettings`
- summary: Patch the settings, creating the row on first use.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `invoice_prefix`: `['string', 'null']`
      - description: 1..=16 characters, `A-Z`, `0-9` and `-`. It becomes part of an invoice
      - type: `['string', 'null']`
    - `stripe_sync_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
- responses:
  - `200`: The settings after the change
    - `application/json`:
      - type: `object (3 properties)`
      - `invoice_prefix` *required*: `string`
        - description: The `INV` in `INV-2026-000042`.
        - type: `string`
      - `stripe_sync_enabled` *required*: `boolean`
        - description: Whether issued invoices are mirrored into the organization's own Stripe
        - type: `boolean`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: The invoice prefix is not a usable one

### `POST /v1/orgs/{org_slug}/billing/subscriptions`

- operationId: `createBillingSubscription`
- summary: Put a customer on a plan.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `anchor_day`: `['integer', 'null']`
      - description: 1..=28, defaulting to `start`'s day of month capped at 28, so every
      - type: `['integer', 'null']`
    - `customer_id` *required*: `string`
      - description: An organization's `SaaS` account being billed (`billing_customers.id`).
      - type: `string`
    - `plan_id` *required*: `string`
      - description: A price book (`billing_plans.id`).
      - type: `string`
    - `start`: `['string', 'null']`
      - description: Defaults to now. The first period runs from here to the first anchor
      - type: `['string', 'null']`
- responses:
  - `201`: Subscription created with its first period
    - `application/json`:
      - type: `object (10 properties)`
      - `anchor_day` *required*: `integer`
        - description: Day of month a period starts, 1..=28.
        - type: `integer`
      - `canceled_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `current_period_end` *required*: `string`
        - type: `string`
      - `current_period_start` *required*: `string`
        - description: Periods are half-open: `[current_period_start, current_period_end)`.
        - type: `string`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `id` *required*: `string`
        - description: A customer's subscription to a plan (`billing_subscriptions.id`).
        - type: `string`
      - `plan_id` *required*: `string`
        - description: A price book (`billing_plans.id`).
        - type: `string`
      - `status` *required*: `string`
        - description: Lifecycle of a subscription.
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such customer or plan in this organization
  - `409`: The customer already has an active subscription
  - `422`: Currency mismatch, archived customer or plan, or anchor_day outside 1..=28

### `POST /v1/orgs/{org_slug}/billing/subscriptions/{subscription_id}/cancel`

- operationId: `cancelBillingSubscription`
- summary: End a subscription, now or at the end of its current period.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `subscription_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `at` *required*: `string`
      - description: When a cancellation takes effect.
      - type: `string`
- responses:
  - `200`: The cancelled subscription
    - `application/json`:
      - type: `object (10 properties)`
      - `anchor_day` *required*: `integer`
        - description: Day of month a period starts, 1..=28.
        - type: `integer`
      - `canceled_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `current_period_end` *required*: `string`
        - type: `string`
      - `current_period_start` *required*: `string`
        - description: Periods are half-open: `[current_period_start, current_period_end)`.
        - type: `string`
      - `customer_id` *required*: `string`
        - description: An organization's `SaaS` account being billed (`billing_customers.id`).
        - type: `string`
      - `id` *required*: `string`
        - description: A customer's subscription to a plan (`billing_subscriptions.id`).
        - type: `string`
      - `plan_id` *required*: `string`
        - description: A price book (`billing_plans.id`).
        - type: `string`
      - `status` *required*: `string`
        - description: Lifecycle of a subscription.
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: No such subscription in this organization

### `GET /v1/orgs/{org_slug}/billing/summary`

- operationId: `getCustomerBillingSummary`
- summary: Counts, the last twelve invoiced months, and the close/invoice health of
§16.
- tags: `Customer Billing v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The organization's customer-billing overview
    - `application/json`:
      - type: `object (8 properties)`
      - `active_customers` *required*: `integer`
        - description: Customers with `status = 'active'`.
        - type: `integer`
      - `active_subscriptions` *required*: `integer`
        - description: Subscriptions with `status = 'active'`.
        - type: `integer`
      - `invoiced_months` *required*: `array<object (4 properties)>`
        - description: The last twelve calendar months that have invoices, newest first.
        - type: `array<object (4 properties)>`
      - `last_close_at`: `['string', 'null']`
        - description: When this organization's most recent hour was closed. `null` means the
        - type: `['string', 'null']`
      - `last_closed_hour`: `['string', 'null']`
        - description: The hour that close covered, so the lag is readable without a second
        - type: `['string', 'null']`
      - `last_invoice_at`: `['string', 'null']`
        - description: `issued_at` of this organization's most recent invoice (§16's
        - type: `['string', 'null']`
      - `meter_count` *required*: `integer`
        - type: `integer`
      - `plan_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `GET /v1/orgs/{org_slug}/blob/status`

- operationId: `blob_status`
- summary: Report the organization's Blob service status.
- tags: `Blob Management v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Blob service status
    - `application/json`:
      - type: `object (4 properties)`
      - `docker_image`: `['string', 'null']`
        - description: Docker image being used
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - description: Whether the Blob service is enabled
        - type: `boolean`
      - `healthy` *required*: `boolean`
        - description: Whether the service is healthy
        - type: `boolean`
      - `version`: `['string', 'null']`
        - description: Current version (if running)
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/branding`

- operationId: `get_branding`
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `dark` *required*: `object`
        - type: `object`
      - `etag` *required*: `string`
        - type: `string`
      - `light` *required*: `object`
        - type: `object`
      - `logo_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - description: The organization's name, so a connected app can show it where its own is the fallback.
        - type: `string`
      - `seed` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `version` *required*: `integer`
        - type: `integer`
  - `304`: Branding is unchanged
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/branding`

- operationId: `update_branding`
- summary: Update one organization's branding.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `brand_accent_color`: `['string', 'null']`
      - type: `['string', 'null']`
    - `brand_primary_color`: `['string', 'null']`
      - type: `['string', 'null']`
    - `logo_blob_key`: `['string', 'null']`
      - type: `['string', 'null']`
    - `theme`: `object (4 properties) | null`
      - type: `object (4 properties) | null`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/consumer-deploys`

- operationId: `create_consumer_deploy`
- summary: Create a consumer deploy draft in this organization.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `app_name` *required*: `string`
      - type: `string`
    - `attach_db` *required*: `boolean`
      - type: `boolean`
    - `env_vars`: `['object', 'null']`
      - type: `['object', 'null']`
    - `template_key` *required*: `string`
      - type: `string`
    - `workspace_id` *required*: `string`
      - description: Identifies a workspace, which belongs to exactly one organization.
      - type: `string`
- responses:
  - `201`: Draft created
    - `application/json`:
      - type: `object (16 properties)`
      - `app_name` *required*: `string`
        - type: `string`
      - `attach_db` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `db_service_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `env_vars` *required*: `object`
        - type: `object`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `managed_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `template_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `workspace_id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/consumer-deploys/feature-status`

- operationId: `get_self_serve_deploy_status`
- summary: Read whether the self-serve deploy surface is enabled for this organization.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Feature flag status
    - `application/json`:
      - type: `object (1 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/consumer-deploys/{id}`

- operationId: `get_consumer_deploy`
- summary: Read a consumer deploy draft. Environment variable values are masked.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deploy draft
    - `application/json`:
      - type: `object (16 properties)`
      - `app_name` *required*: `string`
        - type: `string`
      - `attach_db` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `db_service_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `env_vars` *required*: `object`
        - type: `object`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `managed_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `template_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `workspace_id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization or draft not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/consumer-deploys/{id}/attach-db`

- operationId: `attach_db_to_consumer_deploy`
- summary: Attach a managed database to a draft.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `service_type`: `string`
      - description: Managed DB service type for a consumer deploy.
      - type: `string`
- responses:
  - `200`: Database attached
    - `application/json`:
      - type: `object (16 properties)`
      - `app_name` *required*: `string`
        - type: `string`
      - `attach_db` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `db_service_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `env_vars` *required*: `object`
        - type: `object`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `managed_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `template_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `workspace_id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization or draft not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/consumer-deploys/{id}/deploy`

- operationId: `deploy_consumer_deploy`
- summary: Turn a draft into a real project and deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment started
    - `application/json`:
      - type: `object (5 properties)`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Draft is not ready to deploy
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization or draft not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/consumer-deploys/{id}/domain`

- operationId: `attach_domain_to_consumer_deploy`
- summary: Attach a custom domain to a deployed draft.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `domain` *required*: `string`
      - type: `string`
- responses:
  - `200`: Domain attached, pending: publish `verification` and POST `verify_path` before it claims its hostname or serves traffic
    - `application/json`:
      - type: `object (8 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `environment_domain_id`: `['integer', 'null']`
        - description: The environment domain the attach wrote: the id the verify call takes.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `instructions` *required*: `string`
        - description: What to do next: the TXT record to publish and the verify call.
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `verification`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `verified` *required*: `boolean`
        - description: Whether the domain is verified. Always `false` on attach.
        - type: `boolean`
      - `verify_path`: `['string', 'null']`
        - description: `POST` this path (with the same credentials) once the record is
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization or draft not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/consumer-deploys/{id}/env`

- operationId: `update_consumer_deploy_env`
- summary: Replace a draft's environment variables.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `env_vars` *required*: `object`
      - type: `object`
- responses:
  - `200`: Draft updated
    - `application/json`:
      - type: `object (16 properties)`
      - `app_name` *required*: `string`
        - type: `string`
      - `attach_db` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `db_service_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `env_vars` *required*: `object`
        - type: `object`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `managed_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `template_key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `workspace_id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or the self-serve deploy flag is off for this organization
  - `404`: Organization or draft not found
  - `429`: Rate limit exceeded for this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/deployments/{id}/metrics`

- operationId: `get_deployment_metrics_range`
- summary: Time-series range for one metric on one deployment.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `metric` (query) *required*: `string`
  - `range` (query): `string`
  - `percentile` (query): `['number', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Metric time series data points
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Deployment not found in this organization
  - `503`: Metrics store not available

### `GET /v1/orgs/{org_slug}/deployments/{id}/metrics/latest`

- operationId: `get_deployment_metrics_latest`
- summary: Latest metric values for one deployment.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Map of metric name to latest value
    - `application/json`:
      - type: `object`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Deployment not found in this organization
  - `503`: Metrics store not available

### `GET /v1/orgs/{org_slug}/dns-providers`

- operationId: `list_dns_providers`
- summary: List an organization's DNS providers.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of DNS providers
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/dns-providers`

- operationId: `create_dns_provider`
- summary: Create a DNS provider in an organization.
- description: The credentials are tested before the row is written; a failing test is a
`400` and creates nothing.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `credentials` *required*: `object (3 properties) | object (5 properties) | object (5 properties) | object (2 properties) | object (4 properties) | object (6 properties)`
      - description: DNS provider credentials (API-facing)
      - type: `object (3 properties) | object (5 properties) | object (5 properties) | object (2 properties) | object (4 properties) | object (6 properties)`
    - `description`: `['string', 'null']`
      - description: Optional description
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - description: User-friendly name
      - type: `string`
    - `provider_type` *required*: `string`
      - description: Supported DNS provider types
      - type: `string`
- responses:
  - `201`: DNS provider created
    - `application/json`:
      - type: `object (10 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request or connection test failed
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/dns-providers/{id}`

- operationId: `get_dns_provider`
- summary: Read one DNS provider of an organization.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: DNS provider details
    - `application/json`:
      - type: `object (10 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/dns-providers/{id}`

- operationId: `update_provider`
- summary: Update one DNS provider of an organization.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `credentials`: `object (3 properties) | object (5 properties) | object (5 properties) | object (2 properties) | object (4 properties) | object (6 properties) | null`
      - type: `object (3 properties) | object (5 properties) | object (5 properties) | object (2 properties) | object (4 properties) | object (6 properties) | null`
    - `description`: `['string', 'null']`
      - description: New description
      - type: `['string', 'null']`
    - `is_active`: `['boolean', 'null']`
      - description: Active status
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - description: New name
      - type: `['string', 'null']`
- responses:
  - `200`: DNS provider updated
    - `application/json`:
      - type: `object (10 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/dns-providers/{id}`

- operationId: `delete_dns_provider`
- summary: Delete one DNS provider of an organization.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: DNS provider deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/dns-providers/{id}/domains`

- operationId: `list_managed_domains`
- summary: List the managed domains of one DNS provider.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of managed domains
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/dns-providers/{id}/domains`

- operationId: `add_managed_domain`
- summary: Attach a managed domain to one DNS provider.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `auto_manage`: `boolean`
      - type: `boolean`
    - `domain` *required*: `string`
      - type: `string`
- responses:
  - `201`: Managed domain added
    - `application/json`:
      - type: `object (10 properties)`
      - `auto_manage` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `domain` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `provider_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verification_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `verified` *required*: `boolean`
        - type: `boolean`
      - `verified_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `zone_id`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/dns-providers/{id}/test`

- operationId: `test_provider_connection`
- summary: Test one DNS provider's stored credentials against its upstream API.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connection test result
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/dns-providers/{id}/zones`

- operationId: `list_provider_zones`
- summary: List the zones one DNS provider exposes upstream.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of zones
    - `application/json`:
      - type: `object (1 properties)`
      - `zones` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error
  - `502`: Upstream DNS API error

### `DELETE /v1/orgs/{org_slug}/dns-providers/{provider_id}/domains/{domain}`

- operationId: `remove_managed_domain`
- summary: Detach one managed domain from one DNS provider.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
  - `domain` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Managed domain removed
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider or domain not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/dns-providers/{provider_id}/domains/{domain}/verify`

- operationId: `verify_managed_domain`
- summary: Verify one managed domain against its provider's upstream zone list.
- tags: `DNS Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
  - `domain` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Domain verification result
    - `application/json`:
      - type: `object (10 properties)`
      - `auto_manage` *required*: `boolean`
        - type: `boolean`
      - `created_at` *required*: `string`
        - type: `string`
      - `domain` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `provider_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verification_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `verified` *required*: `boolean`
        - type: `boolean`
      - `verified_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `zone_id`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Provider or domain not found in this organization
  - `500`: Internal server error
  - `502`: Upstream DNS API error

### `GET /v1/orgs/{org_slug}/domains`

- operationId: `list_domains`
- summary: List the domains of one organization (the `kernel.domain` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page. The former
`search` substring parameter is a `prefix` filter on `domain` now.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Domains in the organization
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid collection query (`urn:conusai:collections:*`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains`

- operationId: `create_domain`
- summary: Create a domain in one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `challenge_type`: `string`
      - description: Challenge type for Let's Encrypt validation. Options: "http-01" (default) or "dns-01"
      - type: `string`
    - `domain` *required*: `string`
      - type: `string`
- responses:
  - `201`: Domain created successfully
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/_batch`

- operationId: `get_domains_batch`
- summary: Read back domains of this organization by id.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible domains among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}`

- operationId: `get_domain_by_host`
- summary: Read one domain by hostname, inside one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Domain details
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/domains/by-host/{hostname}`

- operationId: `delete_domain`
- summary: Delete a domain, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Domain deleted successfully
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}/cert-status`

- operationId: `get_on_demand_cert_status`
- summary: Read one hostname's on-demand certificate status.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: On-demand certificate status
    - `application/json`:
      - type: `object (4 properties)`
      - `backoff_until`: `['integer', 'null']`
        - description: On-demand negative-cache deadline (epoch millis), when in backoff.
        - type: `['integer', 'null']`
      - `hostname` *required*: `string`
        - description: SNI hostname.
        - type: `string`
      - `last_attempt`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `status`: `['string', 'null']`
        - description: Current cert lifecycle status from the `domains` row, when one exists.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Hostname not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}/challenge`

- operationId: `get_domain_challenge`
- summary: Read one domain's outstanding ACME challenge, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Challenge details
    - `application/json`:
      - type: `object (3 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `txt_records` *required*: `array<object (2 properties)>`
        - description: Array of TXT records to add to DNS. For wildcards, multiple records are required.
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or challenge not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}/challenge-token`

- operationId: `get_challenge_token`
- summary: Read one domain's DNS-01 challenge token, addressed by hostname.
- description: Returns `text/plain`: the value is pasted straight into a TXT record.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Challenge token
    - `text/plain`:
      - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or challenge not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}/dns-completion`

- operationId: `get_dns_completion`
- summary: Read one domain's DNS propagation status, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: DNS completion status
    - `application/json`:
      - type: `object (2 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/by-host/{hostname}/http-challenge-debug`

- operationId: `get_http_challenge_debug`
- summary: Diagnose why one domain's HTTP-01 challenge is failing, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Challenge debug information
    - `application/json`:
      - type: `object (8 properties)`
      - `challenge_exists` *required*: `boolean`
        - type: `boolean`
      - `challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `challenge_url`: `['string', 'null']`
        - description: The full URL that Let's Encrypt will try to access to validate the challenge
        - type: `['string', 'null']`
      - `dns_a_records` *required*: `array<string>`
        - description: IPv4 addresses the domain points to
        - type: `array<string>`
      - `dns_aaaa_records` *required*: `array<string>`
        - description: IPv6 addresses the domain points to
        - type: `array<string>`
      - `dns_error`: `['string', 'null']`
        - description: Any DNS resolution errors
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `validation_url`: `['string', 'null']`
        - description: The ACME validation URL (internal to ACME protocol)
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains/by-host/{hostname}/provision`

- operationId: `provision_domain`
- summary: Provision a domain certificate, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Certificate provisioning initiated
    - `application/json`:
      - type: `any | any | any`
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains/by-host/{hostname}/renew`

- operationId: `renew_domain`
- summary: Renew a domain certificate, addressed by hostname.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `hostname` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Certificate renewal initiated
    - `application/json`:
      - type: `any | any | any`
  - `202`: DNS challenge created - manual action required
    - `application/json`:
      - type: `object (3 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `txt_records` *required*: `array<object (2 properties)>`
        - description: Array of TXT records to add to DNS. For wildcards, multiple records are required.
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/on-demand-certs`

- operationId: `list_on_demand_certs`
- summary: List the on-demand certificate attempts of one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: On-demand certificate attempts
    - `application/json`:
      - type: `object (4 properties)`
      - `certs` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/{domain_id}`

- operationId: `get_domain_by_id`
- summary: Read one domain by id, inside one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Domain details
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/{domain_id}/order`

- operationId: `get_domain_order`
- summary: Read one domain's ACME order, inside one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: ACME order
    - `application/json`:
      - type: `object (15 properties)`
      - `authorizations`: `any`
        - type: `any`
      - `certificate_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `challenge_validation`: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain_id` *required*: `integer`
        - type: `integer`
      - `email` *required*: `string`
        - type: `string`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `finalize_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `identifiers` *required*: `any`
        - type: `any`
      - `order_url` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or order not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains/{domain_id}/order`

- operationId: `create_or_recreate_order`
- summary: Create or recreate an ACME order for a domain.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Order created successfully
    - `application/json`:
      - type: `object (3 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `txt_records` *required*: `array<object (2 properties)>`
        - description: Array of TXT records to add to DNS. For wildcards, multiple records are required.
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/domains/{domain_id}/order`

- operationId: `cancel_domain_order`
- summary: Cancel the ACME order for a domain.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Order cancelled successfully
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Domain or order not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains/{domain_id}/order/finalize`

- operationId: `finalize_order`
- summary: Finalize the ACME order for a domain.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Order finalized successfully
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Domain or order not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/domains/{domain_id}/setup-dns`

- operationId: `setup_dns_challenge`
- summary: Set up DNS challenge records automatically for a domain.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `dns_provider_id` *required*: `integer`
      - description: The ID of the DNS provider to use for creating the TXT records
      - type: `integer`
- responses:
  - `200`: DNS records created successfully
    - `application/json`:
      - type: `object (5 properties)`
      - `message` *required*: `string`
        - description: Human-readable summary message
        - type: `string`
      - `records_created` *required*: `integer`
        - description: Number of TXT records that were successfully created
        - type: `integer`
      - `results` *required*: `array<object (4 properties)>`
        - description: Results for each individual TXT record
        - type: `array<object (4 properties)>`
      - `success` *required*: `boolean`
        - description: Overall success status (true if all records were created)
        - type: `boolean`
      - `total_records` *required*: `integer`
        - description: Total number of TXT records required for the challenge
        - type: `integer`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or DNS provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/domains/{domain_id}/status`

- operationId: `check_domain_status`
- summary: Read one domain's provisioning status, inside one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Domain status
    - `application/json`:
      - type: `object (15 properties)`
      - `certificate`: `['string', 'null']`
        - description: The PEM-encoded certificate chain (can be displayed in browser or downloaded)
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `dns_challenge_token`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dns_challenge_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `domain` *required*: `string`
        - type: `string`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_wildcard` *required*: `boolean`
        - type: `boolean`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `on_demand_backoff_until`: `['integer', 'null']`
        - description: On-demand TLS negative-cache deadline (epoch millis), when this hostname's
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_method` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-domains`

- operationId: `list_email_domains`
- summary: List the email domains of one organization.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of email domains
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/email-domains`

- operationId: `create_email_domain`
- summary: Create an email domain in one organization.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `domain` *required*: `string`
      - description: Domain name (e.g., "updates.example.com")
      - type: `string`
    - `provider_id` *required*: `integer`
      - description: Provider ID to use for this domain
      - type: `integer`
- responses:
  - `201`: Domain created successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `dns_records` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `domain` *required*: `object (8 properties)`
        - type: `object (8 properties)`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-domains/by-domain/{domain}`

- operationId: `get_domain_by_name`
- summary: Read one email domain by its domain name.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Email domain details with DNS records
    - `application/json`:
      - type: `object (2 properties)`
      - `dns_records` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `domain` *required*: `object (8 properties)`
        - type: `object (8 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-domains/{id}`

- operationId: `get_domain`
- summary: Read one email domain.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Email domain details with DNS records
    - `application/json`:
      - type: `object (2 properties)`
      - `dns_records` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `domain` *required*: `object (8 properties)`
        - type: `object (8 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/email-domains/{id}`

- operationId: `delete_email_domain`
- summary: Delete one email domain.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Domain deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-domains/{id}/dns-records`

- operationId: `get_domain_dns_records`
- summary: Read the DNS records of one email domain.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: DNS records for the domain
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/email-domains/{id}/setup-dns`

- operationId: `setup_dns`
- summary: Create the DNS records of one email domain through a DNS provider.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `dns_provider_id` *required*: `integer`
      - description: The ID of the DNS provider to use for creating records
      - type: `integer`
- responses:
  - `200`: DNS records setup result
    - `application/json`:
      - type: `object (5 properties)`
      - `message` *required*: `string`
        - description: Human-readable summary message
        - type: `string`
      - `records_created` *required*: `integer`
        - description: Number of records that were successfully created
        - type: `integer`
      - `results` *required*: `array<object (5 properties)>`
        - description: Results for each individual record
        - type: `array<object (5 properties)>`
      - `success` *required*: `boolean`
        - description: Overall success status
        - type: `boolean`
      - `total_records` *required*: `integer`
        - description: Total number of records attempted
        - type: `integer`
  - `400`: Invalid request or DNS provider not configured
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/email-domains/{id}/verify`

- operationId: `verify_domain`
- summary: Verify one email domain's DNS records.
- tags: `Email Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Domain verification result with DNS records
    - `application/json`:
      - type: `object (2 properties)`
      - `dns_records` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `domain` *required*: `object (8 properties)`
        - type: `object (8 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Domain or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-providers`

- operationId: `list_email_providers`
- summary: List the email providers of one organization.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of email providers
    - `application/json`:
      - type: `array<object (12 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/email-providers`

- operationId: `create_email_provider`
- summary: Create an email provider in one organization.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (10 properties)`
    - `from_address`: `['string', 'null']`
      - description: Sender address for platform mail (invitations, password resets,
      - type: `['string', 'null']`
    - `from_name`: `['string', 'null']`
      - description: Display name paired with `from_address`. Defaults to `ConusAI`.
      - type: `['string', 'null']`
    - `is_default`: `boolean`
      - description: Make this the organization's default sender (clears the previous one).
      - type: `boolean`
    - `name` *required*: `string`
      - description: User-friendly name for the provider
      - type: `string`
    - `provider_type` *required*: `string`
      - type: `string`
    - `region` *required*: `string`
      - description: Cloud region. For SMTP this is informational only — the host/port carry the real routing.
      - type: `string`
    - `scaleway_credentials`: `object (2 properties) | null`
      - type: `object (2 properties) | null`
    - `ses_credentials`: `object (2 properties) | null`
      - type: `object (2 properties) | null`
    - `smtp_credentials`: `object (6 properties) | null`
      - type: `object (6 properties) | null`
    - `sns_topic_arn`: `['string', 'null']`
      - description: SNS topic ARN for SES bounce/complaint notifications. SES-only.
      - type: `['string', 'null']`
- responses:
  - `201`: Provider created successfully
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `from_address`: `['string', 'null']`
        - description: Sender address for platform mail sent through this provider.
        - type: `['string', 'null']`
      - `from_name`: `['string', 'null']`
        - description: Sender display name for platform mail.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - description: Whether this is the organization's default sender.
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `sns_topic_arn`: `['string', 'null']`
        - description: SNS topic ARN for SES bounce/complaint notifications. SES-only.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-providers/{id}`

- operationId: `get_email_provider`
- summary: Read one email provider.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Email provider details
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `from_address`: `['string', 'null']`
        - description: Sender address for platform mail sent through this provider.
        - type: `['string', 'null']`
      - `from_name`: `['string', 'null']`
        - description: Sender display name for platform mail.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - description: Whether this is the organization's default sender.
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `sns_topic_arn`: `['string', 'null']`
        - description: SNS topic ARN for SES bounce/complaint notifications. SES-only.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/email-providers/{id}`

- operationId: `update_email_provider`
- summary: Update one email provider.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (10 properties)`
    - `from_address`: `['string', 'null']`
      - description: Double-Option like `sns_topic_arn`. Sender address for platform mail.
      - type: `['string', 'null']`
    - `from_name`: `['string', 'null']`
      - description: Double-Option like `sns_topic_arn`. Sender display name.
      - type: `['string', 'null']`
    - `is_active`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - description: `true` makes this the organization's default sender (clearing the
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `region`: `['string', 'null']`
      - type: `['string', 'null']`
    - `scaleway_credentials`: `object (2 properties) | null`
      - type: `object (2 properties) | null`
    - `ses_credentials`: `object (2 properties) | null`
      - type: `object (2 properties) | null`
    - `smtp_credentials`: `object (6 properties) | null`
      - type: `object (6 properties) | null`
    - `sns_topic_arn`: `['string', 'null']`
      - description: Double-Option: absent = leave unchanged, present-null = clear,
      - type: `['string', 'null']`
- responses:
  - `200`: Provider updated
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `credentials` *required*: `any`
        - description: Masked credentials for display
        - type: `any`
      - `from_address`: `['string', 'null']`
        - description: Sender address for platform mail sent through this provider.
        - type: `['string', 'null']`
      - `from_name`: `['string', 'null']`
        - description: Sender display name for platform mail.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - description: Whether this is the organization's default sender.
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `region` *required*: `string`
        - type: `string`
      - `sns_topic_arn`: `['string', 'null']`
        - description: SNS topic ARN for SES bounce/complaint notifications. SES-only.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `409`: Provider type mismatch
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/email-providers/{id}`

- operationId: `delete_email_provider`
- summary: Delete one email provider.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Provider deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/email-providers/{id}/test`

- operationId: `test_provider`
- summary: Send a test email through one email provider.
- tags: `Email Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `from` *required*: `string`
      - description: Sender email address (must be verified with the provider)
      - type: `string`
    - `from_name`: `['string', 'null']`
      - description: Sender display name
      - type: `['string', 'null']`
- responses:
  - `200`: Test email result
    - `application/json`:
      - type: `object (4 properties)`
      - `error`: `['string', 'null']`
        - description: Error message if the test failed
        - type: `['string', 'null']`
      - `provider_message_id`: `['string', 'null']`
        - description: Provider message ID if successful
        - type: `['string', 'null']`
      - `sent_to` *required*: `string`
        - description: The email address the test was sent to
        - type: `string`
      - `success` *required*: `boolean`
        - description: Whether the test email was sent successfully
        - type: `boolean`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/email-sender-status`

- operationId: `get_org_email_sender_status`
- summary: Check sender availability for a member's organization without exposing provider details.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Whether transactional email has an org or platform sender
    - `application/json`:
      - type: `object (1 properties)`
      - `email_configured` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `404`: Organization not found
  - `500`: Could not resolve email sender availability

### `GET /v1/orgs/{org_slug}/emails`

- operationId: `list_emails`
- summary: List the emails of one organization.
- tags: `Emails v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (query): `['integer', 'null']`
  - `project_id` (query): `['integer', 'null']`
  - `status` (query): `['string', 'null']`
  - `from_address` (query): `['string', 'null']`
  - `tags` (query): `['string', 'null']`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of emails
    - `application/json`:
      - type: `object (4 properties)`
      - `data` *required*: `array<object (26 properties)>`
        - type: `array<object (26 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `400`: A tags filter outside the tag grammar (problem type .../email/tag-invalid)
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/emails`

- operationId: `send_email`
- summary: Send an email from one organization.
- tags: `Emails v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (13 properties)`
    - `bcc`: `['array', 'null']`
      - description: BCC recipients
      - type: `['array', 'null']`
    - `cc`: `['array', 'null']`
      - description: CC recipients
      - type: `['array', 'null']`
    - `from` *required*: `string`
      - description: Sender email address (domain will be auto-extracted for lookup)
      - type: `string`
    - `from_name`: `['string', 'null']`
      - description: Sender display name
      - type: `['string', 'null']`
    - `headers`: `['object', 'null']`
      - description: Custom headers
      - type: `['object', 'null']`
    - `html`: `['string', 'null']`
      - description: HTML body content
      - type: `['string', 'null']`
    - `reply_to`: `['string', 'null']`
      - description: Reply-to address
      - type: `['string', 'null']`
    - `subject` *required*: `string`
      - description: Email subject
      - type: `string`
    - `tags`: `['array', 'null']`
      - description: Tags for categorization and the list's `tags` filter: at most 20, each 1 to 128
      - type: `['array', 'null']`
    - `text`: `['string', 'null']`
      - description: Plain text body content
      - type: `['string', 'null']`
    - `to` *required*: `array<string>`
      - description: Recipient email addresses
      - type: `array<string>`
    - `track_clicks`: `['boolean', 'null']`
      - description: Enable click tracking (link rewriting). Defaults to false.
      - type: `['boolean', 'null']`
    - `track_opens`: `['boolean', 'null']`
      - description: Enable open tracking (tracking pixel injection). Defaults to false.
      - type: `['boolean', 'null']`
- responses:
  - `201`: Email sent successfully
    - `application/json`:
      - type: `object (3 properties)`
      - `id` *required*: `string`
        - description: Email ID
        - type: `string`
      - `provider_message_id`: `['string', 'null']`
        - description: Provider message ID
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Email status
        - type: `string`
  - `400`: Invalid request, a tag outside the tag grammar (problem type .../email/tag-invalid) or domain not verified
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/events`

- operationId: `get_global_events`
- summary: List the tracking events of one organization.
- tags: `Email Tracking v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `event_type` (query): `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Paginated tracking events
    - `application/json`:
      - type: `object (4 properties)`
      - `events` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/events/stats`

- operationId: `get_global_event_stats`
- summary: Read the aggregate tracking statistics of one organization.
- tags: `Email Tracking v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Global tracking statistics
    - `application/json`:
      - type: `object (8 properties)`
      - `bounce_rate`: `['number', 'null']`
        - type: `['number', 'null']`
      - `bounced` *required*: `integer`
        - type: `integer`
      - `click_rate`: `['number', 'null']`
        - type: `['number', 'null']`
      - `clicked` *required*: `integer`
        - type: `integer`
      - `complained` *required*: `integer`
        - type: `integer`
      - `delivered` *required*: `integer`
        - type: `integer`
      - `open_rate`: `['number', 'null']`
        - type: `['number', 'null']`
      - `opened` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/stats`

- operationId: `get_email_stats`
- summary: Read the email statistics of one organization.
- tags: `Emails v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Email statistics
    - `application/json`:
      - type: `object (5 properties)`
      - `captured` *required*: `integer`
        - description: Emails captured without sending (Mailhog mode - no provider configured)
        - type: `integer`
      - `failed` *required*: `integer`
        - type: `integer`
      - `queued` *required*: `integer`
        - type: `integer`
      - `sent` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/{id}`

- operationId: `get_email`
- summary: Read one email.
- tags: `Emails v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Email details
    - `application/json`:
      - type: `object (26 properties)`
      - `bcc_addresses`: `['array', 'null']`
        - type: `['array', 'null']`
      - `cc_addresses`: `['array', 'null']`
        - type: `['array', 'null']`
      - `click_count` *required*: `integer`
        - description: Number of times links in the email were clicked
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `first_clicked_at`: `['string', 'null']`
        - description: When a link was first clicked
        - type: `['string', 'null']`
      - `first_opened_at`: `['string', 'null']`
        - description: When the email was first opened
        - type: `['string', 'null']`
      - `from_address` *required*: `string`
        - type: `string`
      - `from_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `headers`: `['object', 'null']`
        - type: `['object', 'null']`
      - `html_body`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `open_count` *required*: `integer`
        - description: Number of times the email was opened
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `provider_message_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `reply_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `sent_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `subject` *required*: `string`
        - type: `string`
      - `tags`: `['array', 'null']`
        - type: `['array', 'null']`
      - `text_body`: `['string', 'null']`
        - type: `['string', 'null']`
      - `to_addresses` *required*: `array<string>`
        - type: `array<string>`
      - `track_clicks` *required*: `boolean`
        - description: Whether click tracking is enabled
        - type: `boolean`
      - `track_opens` *required*: `boolean`
        - description: Whether open tracking is enabled
        - type: `boolean`
      - `tracked_html_body`: `['string', 'null']`
        - description: The final HTML sent to the provider (with tracking pixel and rewritten links)
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Email or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/{id}/tracking`

- operationId: `get_email_tracking`
- summary: Read the tracking summary of one email.
- tags: `Email Tracking v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Tracking summary
    - `application/json`:
      - type: `object (10 properties)`
      - `click_count` *required*: `integer`
        - type: `integer`
      - `email_id` *required*: `string`
        - type: `string`
      - `first_clicked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `first_opened_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `links` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `open_count` *required*: `integer`
        - type: `integer`
      - `track_clicks` *required*: `boolean`
        - type: `boolean`
      - `track_opens` *required*: `boolean`
        - type: `boolean`
      - `unique_clicks` *required*: `integer`
        - type: `integer`
      - `unique_opens` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Email or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/{id}/tracking/events`

- operationId: `get_email_events`
- summary: List the tracking events of one email.
- tags: `Email Tracking v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `event_type` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Tracking events
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Email or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/emails/{id}/tracking/links`

- operationId: `get_email_links`
- summary: List the tracked links of one email.
- tags: `Email Tracking v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Tracked links
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Email or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/files/{file_path}`

- operationId: `get_org_file`
- summary: Read a file stored for the path's organization.
- tags: `Files`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `file_path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: File content
    - `application/octet-stream`:
      - type: `any`
  - `401`: Authentication required
  - `403`: The caller's organization role lacks FilesRead
  - `404`: Organization or file not found, or access denied

### `GET /v1/orgs/{org_slug}/git-connections`

- operationId: `list_connections`
- summary: List the active git-provider connections of one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
  - `sort` (query): `string`
  - `direction` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Connections in the organization
    - `application/json`:
      - type: `object (4 properties)`
      - `connections` *required*: `array<object (17 properties)>`
        - type: `array<object (17 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Organization not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/git-connections/{connection_id}`

- operationId: `delete_connection`
- summary: Delete one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Connection deleted
  - `400`: Connection is in use by projects
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-connections/{connection_id}/activate`

- operationId: `activate_connection`
- summary: Activate one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connection activated
  - `400`: Owning provider is deactivated
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-connections/{connection_id}/deactivate`

- operationId: `deactivate_connection`
- summary: Deactivate one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connection deactivated
  - `400`: Connection is in use by projects
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-connections/{connection_id}/health-check`

- operationId: `run_connection_health_check`
- summary: Run an on-demand health check for one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Health check completed
    - `application/json`:
      - type: `object (17 properties)`
      - `account_name` *required*: `string`
        - type: `string`
      - `account_type` *required*: `string`
        - type: `string`
      - `consecutive_health_failures` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `health_message`: `['string', 'null']`
        - description: Human-readable reason when `health_status` is "unhealthy"; null otherwise.
        - type: `['string', 'null']`
      - `health_status` *required*: `string`
        - description: Current health status: "healthy", "unhealthy", or "unknown".
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `installation_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_expired` *required*: `boolean`
        - type: `boolean`
      - `last_health_check_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_synced_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `provider_id` *required*: `integer`
        - type: `integer`
      - `synced_repository_count` *required*: `integer`
        - description: Running count of repositories persisted by the current (or most
        - type: `integer`
      - `syncing` *required*: `boolean`
        - type: `boolean`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-connections/{connection_id}/repositories`

- operationId: `list_repositories_by_connection`
- summary: List the repositories reachable through one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
  - `sort` (query): `string`
  - `direction` (query): `string`
  - `search` (query): `string`
  - `owner` (query): `string`
  - `language` (query): `string`
  - `private` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Repositories of the connection
    - `application/json`:
      - type: `object (2 properties)`
      - `repositories` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-connections/{connection_id}/sync`

- operationId: `sync_repositories`
- summary: Start a background repository sync for one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Repository sync started
    - `application/json`:
      - type: `object (3 properties)`
      - `connection_id` *required*: `integer`
        - type: `integer`
      - `started_at` *required*: `string`
        - type: `string`
      - `syncing` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `409`: Sync already in progress
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-connections/{connection_id}/update-token`

- operationId: `update_connection_token`
- summary: Update the stored access token of one connection.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `access_token` *required*: `string`
      - type: `string`
    - `refresh_token`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Token updated
    - `application/json`:
      - type: `object (3 properties)`
      - `connection_id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `message` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-connections/{connection_id}/validate`

- operationId: `validate_connection`
- summary: Validate one connection by probing its access token.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Validation result
    - `application/json`:
      - type: `object (3 properties)`
      - `connection_id` *required*: `integer`
        - type: `integer`
      - `is_valid` *required*: `boolean`
        - type: `boolean`
      - `message` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Connection not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-providers`

- operationId: `list_git_providers`
- summary: List the active git providers of one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Providers in the organization
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers`

- operationId: `create_git_provider`
- summary: Create a git provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `api_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `auth_config` *required*: `any`
      - type: `any`
    - `auth_method` *required*: `string`
      - type: `string`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_default` *required*: `boolean`
      - type: `boolean`
    - `name` *required*: `string`
      - type: `string`
    - `provider_type` *required*: `string`
      - type: `string`
    - `webhook_secret`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/bitbucket`

- operationId: `create_bitbucket_provider`
- summary: Create a Bitbucket provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `auth` *required*: `object (2 properties) | object (3 properties)`
      - description: Authentication input for a Bitbucket Cloud provider. Use `access_token` for
      - type: `object (2 properties) | object (3 properties)`
    - `name` *required*: `string`
      - description: Display name for this provider.
      - type: `string`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/generic`

- operationId: `create_generic_provider`
- summary: Create a generic (manual) git provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `base_url`: `['string', 'null']`
      - description: Optional base URL of the git host for display purposes (no API is called).
      - type: `['string', 'null']`
    - `clone_url` *required*: `string`
      - description: HTTPS clone URL for the repository, e.g. `https://git.example.com/org/repo.git`.
      - type: `string`
    - `name` *required*: `string`
      - description: Display name for this provider.
      - type: `string`
    - `token`: `['string', 'null']`
      - description: Access token or password. Omit (or set to `null`) for public repositories.
      - type: `['string', 'null']`
    - `token_username`: `['string', 'null']`
      - description: HTTP Basic username used with the token. Defaults to `x-access-token` when
      - type: `['string', 'null']`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/gitea/pat`

- operationId: `create_gitea_pat_provider`
- summary: Create a Gitea personal-access-token provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `base_url` *required*: `string`
      - description: HTTPS base URL of the Gitea instance, e.g. `https://git.example.com`.
      - type: `string`
    - `name` *required*: `string`
      - description: Display name for this provider.
      - type: `string`
    - `token` *required*: `string`
      - description: Personal access token issued by the Gitea instance.
      - type: `string`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/github/app-manifest`

- operationId: `create_github_app_manifest`
- summary: Register a pending GitHub App manifest creation in one organization.
- description: Ux-observations #10: the manifest flow used to generate the `state` UUID
client-side, so the conversion callback had no organization to file the
converted app under and it landed in the platform org, invisible to the
tenant. This endpoint has no legacy twin — the legacy flow never
registered anything, which was the bug.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `workspace_slug` *required*: `string`
      - description: The console workspace scope the manifest flow is started from; the
      - type: `string`
- responses:
  - `201`: Pending manifest creation registered
    - `application/json`:
      - type: `object (2 properties)`
      - `expires_at` *required*: `string`
        - description: After this time the state is refused by the conversion callback.
        - type: `string`
      - `state` *required*: `string`
        - description: Server-generated state UUID bound to this organization. The console
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/github/pat`

- operationId: `create_github_pat_provider`
- summary: Create a GitHub personal-access-token provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `name` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - type: `string`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/gitlab/oauth`

- operationId: `create_gitlab_oauth_provider`
- summary: Create a GitLab OAuth provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `client_id` *required*: `string`
      - type: `string`
    - `client_secret` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `redirect_uri` *required*: `string`
      - type: `string`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/gitlab/pat`

- operationId: `create_gitlab_pat_provider`
- summary: Create a GitLab personal-access-token provider in one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - type: `string`
- responses:
  - `201`: Provider created
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-providers/{provider_id}`

- operationId: `get_git_provider`
- summary: Read one git provider inside one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Provider details
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/git-providers/{provider_id}`

- operationId: `delete_git_provider`
- summary: Delete one git provider inside one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Provider deleted
  - `400`: Provider still has connections
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/{provider_id}/activate`

- operationId: `activate_provider`
- summary: Activate one provider.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Provider activated
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-providers/{provider_id}/connections`

- operationId: `get_provider_connections`
- summary: List the connections belonging to one provider.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Connections of the provider
    - `application/json`:
      - type: `array<object (17 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/git-providers/{provider_id}/credentials`

- operationId: `update_git_provider_credentials`
- summary: Partially update the credentials of one provider.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `app_id`: `['string', 'null']`
      - description: Application ID (GitHub App integer as string; GitLab App string).
      - type: `['string', 'null']`
    - `app_secret`: `['string', 'null']`
      - description: GitLab App secret (not used by GitHub App — use `client_secret`).
      - type: `['string', 'null']`
    - `client_id`: `['string', 'null']`
      - description: OAuth client ID (GitLab OAuth, GitHub App).
      - type: `['string', 'null']`
    - `client_secret`: `['string', 'null']`
      - description: OAuth client secret (GitLab OAuth, GitHub App).
      - type: `['string', 'null']`
    - `private_key`: `['string', 'null']`
      - description: GitHub App private key (PEM).
      - type: `['string', 'null']`
    - `redirect_uri`: `['string', 'null']`
      - description: OAuth redirect URI (GitLab OAuth / GitLab App).
      - type: `['string', 'null']`
    - `token`: `['string', 'null']`
      - description: PAT for PAT-type providers.
      - type: `['string', 'null']`
    - `webhook_secret`: `['string', 'null']`
      - description: GitHub App webhook secret.
      - type: `['string', 'null']`
- responses:
  - `200`: Credentials updated
    - `application/json`:
      - type: `object (9 properties)`
      - `auth_method` *required*: `string`
        - type: `string`
      - `base_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `provider_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/{provider_id}/deactivate`

- operationId: `deactivate_provider`
- summary: Deactivate one provider.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Provider deactivated
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/git-providers/{provider_id}/deletion-check`

- operationId: `check_provider_deletion_safety`
- summary: Report whether one provider can be deleted, and what still uses it.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deletion check result
    - `application/json`:
      - type: `object (3 properties)`
      - `can_delete` *required*: `boolean`
        - type: `boolean`
      - `message` *required*: `string`
        - type: `string`
      - `projects_in_use` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/git-providers/{provider_id}/github/installations/reconcile`

- operationId: `reconcile_github_app_installation`
- summary: Verify and reconcile a GitHub App installation into this organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `installation_id` *required*: `integer`
      - description: Installation id returned by GitHub's App installation flow.
      - type: `integer`
- responses:
  - `200`: Verified installation connection
    - `application/json`:
      - type: `object (17 properties)`
      - `account_name` *required*: `string`
        - type: `string`
      - `account_type` *required*: `string`
        - type: `string`
      - `consecutive_health_failures` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `health_message`: `['string', 'null']`
        - description: Human-readable reason when `health_status` is "unhealthy"; null otherwise.
        - type: `['string', 'null']`
      - `health_status` *required*: `string`
        - description: Current health status: "healthy", "unhealthy", or "unknown".
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `installation_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `is_expired` *required*: `boolean`
        - type: `boolean`
      - `last_health_check_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_synced_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `provider_id` *required*: `integer`
        - type: `integer`
      - `synced_repository_count` *required*: `integer`
        - description: Running count of repositories persisted by the current (or most
        - type: `integer`
      - `syncing` *required*: `boolean`
        - type: `boolean`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid installation id
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or installation not found
  - `502`: GitHub verification failed

### `POST /v1/orgs/{org_slug}/git-providers/{provider_id}/github/installations/start`

- operationId: `start_github_installation`
- tags: `Git Providers`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `workspace_id` *required*: `string`
      - description: Identifies a workspace, which belongs to exactly one organization.
      - type: `string`
- responses:
  - `200`: Opaque one-time install return state
    - `application/json`:
      - type: `object (1 properties)`
      - `state` *required*: `string`
        - type: `string`
  - `401`: Authentication required
  - `403`: Git provider write permission required
  - `404`: Provider or workspace not found

### `GET /v1/orgs/{org_slug}/git-providers/{provider_id}/oauth/authorize`

- operationId: `start_git_provider_oauth`
- summary: Begin the OAuth authorization flow for one provider.
- description: Only the *authorize* leg is mirrored. The callback stays on its legacy path
because that URL is registered with the upstream OAuth application; see the
module docs.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `302`: Redirect to the OAuth provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/git-providers/{provider_id}/safe-delete`

- operationId: `delete_provider_safely`
- summary: Delete one provider together with everything that only it owns.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Provider deleted
  - `400`: Provider is still in use
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/invites`

- operationId: `list_invites`
- summary: List an organization's outstanding invites (the `kernel.invitation`
collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/invites`

- operationId: `issue_invite`
- summary: Issue an invite into an organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `email` *required*: `string`
      - type: `string`
    - `org_role` *required*: `string`
      - type: `string`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (13 properties)`
      - `accepted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `delivery_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `delivery_status` *required*: `string`
        - type: `string`
      - `email` *required*: `string`
        - type: `string`
      - `expires_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `invite_url`: `['string', 'null']`
        - description: One-time acceptance link (`{external_url}/auth/accept-invite?token=…`).
        - type: `['string', 'null']`
      - `last_attempted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/invites/_batch`

- operationId: `get_invites_batch`
- summary: Read back outstanding invites of an organization by id.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/invites/{invite_id}`

- operationId: `revoke_invite`
- summary: Revoke an outstanding invite.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invite_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: No Content
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/invites/{invite_id}/resend`

- operationId: `resend_invite`
- summary: Resend an outstanding invite email.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `invite_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (13 properties)`
      - `accepted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `delivery_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `delivery_status` *required*: `string`
        - type: `string`
      - `email` *required*: `string`
        - type: `string`
      - `expires_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `invite_url`: `['string', 'null']`
        - description: One-time acceptance link (`{external_url}/auth/accept-invite?token=…`).
        - type: `['string', 'null']`
      - `last_attempted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/kv/disable`

- operationId: `kv_disable`
- summary: Disable the KV service of a path-named organization.
- tags: `KV Management v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: KV service disabled
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - description: Status message
        - type: `string`
      - `success` *required*: `boolean`
        - description: Whether the service was successfully disabled
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found, or KV service not enabled
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/kv/enable`

- operationId: `kv_enable`
- summary: Enable the KV service of a path-named organization.
- description: Delegates to the legacy body: the service is created in the session's
active workspace (validated), shared by both grammars.
- tags: `KV Management v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `docker_image`: `['string', 'null']`
      - description: Docker image to use (optional, uses default if not provided)
      - type: `['string', 'null']`
    - `max_memory`: `['string', 'null']`
      - description: Maximum memory allocation (e.g., "256mb", "1gb")
      - type: `['string', 'null']`
    - `persistence`: `boolean`
      - description: Enable data persistence
      - type: `boolean`
- responses:
  - `200`: KV service enabled
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Status message
        - type: `string`
      - `status` *required*: `object (4 properties)`
        - description: Response for KV service status
        - type: `object (4 properties)`
      - `success` *required*: `boolean`
        - description: Whether the service was successfully enabled
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/kv/status`

- operationId: `kv_status`
- summary: Read the KV service status of a path-named organization.
- tags: `KV Management v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: KV service status
    - `application/json`:
      - type: `object (4 properties)`
      - `docker_image`: `['string', 'null']`
        - description: Docker image being used
        - type: `['string', 'null']`
      - `enabled` *required*: `boolean`
        - description: Whether the KV service is enabled
        - type: `boolean`
      - `healthy` *required*: `boolean`
        - description: Whether the underlying Redis service is healthy
        - type: `boolean`
      - `version`: `['string', 'null']`
        - description: Service version
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/kv/update`

- operationId: `kv_update`
- summary: Update the KV service configuration of a path-named organization.
- tags: `KV Management v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `docker_image`: `['string', 'null']`
      - description: Docker image to use (e.g., "valkey/valkey:9-trixie")
      - type: `['string', 'null']`
- responses:
  - `200`: KV service updated
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - description: Status message
        - type: `string`
      - `status` *required*: `object (4 properties)`
        - description: Response for KV service status
        - type: `object (4 properties)`
      - `success` *required*: `boolean`
        - description: Whether the operation succeeded
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found, or KV service not enabled
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/live`

- operationId: `open_live_stream`
- summary: Open a CLP/1 change stream for the organization.
- tags: `Live`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `after`: `['string', 'null']`
      - description: The last processed cursor, or null to start at the current watermark.
      - type: `['string', 'null']`
    - `entities` *required*: `array<string>`
      - description: Entities to follow (`{service}.{entity}` / `kernel.{entity}`), at most 64.
      - type: `array<string>`
    - `protocol` *required*: `string`
      - description: Always `clp/1`.
      - type: `string`
    - `topics` *required*: `array<object (3 properties)>`
      - description: Topics, at most 32; empty means every workspace the caller may read.
      - type: `array<object (3 properties)>`
- responses:
  - `200`: CLP/1 Server-Sent Events: hello, changes, watermark, resync, revoked, error
    - `text/event-stream`:
      - type: `any`
  - `400`: Malformed body, unsupported protocol, invalid cursor, too many entities or topics (urn:conusai:live:invalid-request, :unsupported-protocol, :invalid-cursor, :too-many-entities, :too-many-topics)
  - `401`: Unauthorized
  - `403`: Not a member, or credential not supported (urn:conusai:live:credential-not-supported)
  - `404`: Organization not found
  - `429`: Too many streams for this session (urn:conusai:live:too-many-streams)
  - `503`: Too many streams for this organization, or the log is unavailable; Retry-After

### `GET /v1/orgs/{org_slug}/me/permissions`

- operationId: `get_my_org_permissions`
- summary: The caller's organization role and every permission it grants.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The caller's effective organization permissions
    - `application/json`:
      - type: `object (6 properties)`
      - `credential_permissions` *required*: `array<string>`
        - description: Every permission the caller's credential holds (its platform role, an
        - type: `array<string>`
      - `credential_scopes` *required*: `array<string>`
        - description: Effective scopes after the custom-key or deployment-token ceiling.
        - type: `array<string>`
      - `is_super_admin` *required*: `boolean`
        - description: Whether the caller bypasses organization RBAC as a platform super-admin
        - type: `boolean`
      - `permissions` *required*: `array<string>`
        - description: Every permission organization RBAC grants the caller here, as the
        - type: `array<string>`
      - `role`: `['string', 'null']`
        - description: The caller's organization role (`owner`, `admin`, `developer`,
        - type: `['string', 'null']`
      - `scopes` *required*: `array<string>`
        - description: Registered scopes granted in services enabled for this organization.
        - type: `array<string>`
  - `401`: Unauthorized
  - `404`: Organization not found, or the caller is not a member
  - `500`: Service scope authority unavailable

### `GET /v1/orgs/{org_slug}/me/services`

- operationId: `my_services`
- summary: The services enabled for an organization, with the caller's scopes in
each.
- description: Any member may ask. Hiding an entry in the console is cosmetic; the
service's own routes answer the typed `404` when it is not enabled.
- tags: `Modules`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The services enabled for this organization, in name order; empty when none is
    - `application/json`:
      - type: `object (1 properties)`
      - `services` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found, or the caller is not a member
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/members`

- operationId: `list_members`
- summary: List an organization's members (the `kernel.member` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page. The key `id` is
the membership row id.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/members`

- operationId: `add_member`
- summary: Add a member to an organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `org_role` *required*: `string`
      - type: `string`
    - `user_id` *required*: `integer`
      - type: `integer`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `email_verified`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_sso`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `mfa_enabled`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_id` *required*: `integer`
        - type: `integer`
      - `user_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/members/_batch`

- operationId: `get_members_batch`
- summary: Read back members of an organization by membership id.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/members/{user_id}`

- operationId: `update_member_role`
- summary: Change a member's organization role.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `user_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `org_role` *required*: `string`
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `email_verified`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_sso`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `mfa_enabled`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_id` *required*: `integer`
        - type: `integer`
      - `user_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/members/{user_id}`

- operationId: `remove_member`
- summary: Remove a member from an organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `user_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `email_verified`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_sso`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `mfa_enabled`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_id` *required*: `integer`
        - type: `integer`
      - `user_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/modules`

- operationId: `list_modules`
- summary: Every module installed on this instance, with this organization's
enablement and readiness.
- tags: `Modules`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Every installed module, in name order; empty when the instance has none
    - `application/json`:
      - type: `object (1 properties)`
      - `modules` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The caller lacks `modules:manage`
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found, or the caller is not a member
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/modules/{name}/disable`

- operationId: `disable_module`
- summary: Disable a module for this organization. Its routes answer the typed
`404`, its tools are withdrawn and its data is kept.
- description: Idempotent: disabling a disabled module changes nothing and writes no
audit row.
- tags: `Modules`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The module is disabled; `changed` is false when it already was
    - `application/json`:
      - type: `object (2 properties)`
      - `changed` *required*: `boolean`
        - description: `false` when the module already was in the requested state; nothing
        - type: `boolean`
      - `module` *required*: `object (12 properties)`
        - description: One installed service.
        - type: `object (12 properties)`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The caller lacks `modules:manage`
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found or the caller is not a member, or (`error_code` `SERVICE_NOT_INSTALLED`) no module with this name is installed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The module is changing, or its data obligations cannot be retained
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/modules/{name}/enable`

- operationId: `enable_module`
- summary: Enable a module for this organization.
- description: Checks the plan entitlement first (`402`, or `403` while the licence is
degraded or the module is not rolled out), then readiness (`409`
`urn:conusai:service:not-ready`). Idempotent: enabling an enabled module
changes nothing and writes no audit row.
- tags: `Modules`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The module is enabled; `changed` is false when it already was
    - `application/json`:
      - type: `object (2 properties)`
      - `changed` *required*: `boolean`
        - description: `false` when the module already was in the requested state; nothing
        - type: `boolean`
      - `module` *required*: `object (12 properties)`
        - description: One installed service.
        - type: `object (12 properties)`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization's plan does not include the module (`error_code` `SERVICE_NOT_ENTITLED`)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The caller lacks `modules:manage`, the licence is degraded or the module is not rolled out to this organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization not found or the caller is not a member, or (`error_code` `SERVICE_NOT_INSTALLED`) no module with this name is installed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: (`type` `urn:conusai:service:not-ready`) the module is installed but not ready at its current generation, or it is changing
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The service registry could not answer
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/notification-providers`

- operationId: `list_notification_providers`
- summary: List the notification providers of one organization (plus the platform's).
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved providers
    - `application/json`:
      - type: `array<object (14 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/notification-providers`

- operationId: `create_notification_provider`
- summary: Create a notification provider in one organization.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `channel`: `string | null`
      - type: `string | null`
    - `credentials`: `any`
      - description: Secrets for the transport; encrypted at rest.
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `owner`: `string | null`
      - type: `string | null`
    - `settings`: `any`
      - description: Non-secret settings for the transport (see the per-transport schema).
      - type: `any`
    - `transport` *required*: `string`
      - description: How a channel delivers.
      - type: `string`
- responses:
  - `201`: Successfully created provider
    - `application/json`:
      - type: `object (14 properties)`
      - `channel` *required*: `string`
        - description: A delivery channel: the kind of recipient address.
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `credentials` *required*: `any`
        - description: Secret fields with their values masked (`***`); keys show what is set.
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `health_status`: `['string', 'null']`
        - description: `healthy` / `unhealthy` after the last test; `null` if never tested.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `last_checked_at`: `['integer', 'null']`
        - description: Unix milliseconds of the last test.
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for platform-owned providers.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `settings` *required*: `any`
        - description: Non-secret, transport-specific settings.
        - type: `any`
      - `transport` *required*: `string`
        - description: How a channel delivers.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/notification-providers/{id}`

- operationId: `get_notification_provider`
- summary: Read one notification provider.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved provider
    - `application/json`:
      - type: `object (14 properties)`
      - `channel` *required*: `string`
        - description: A delivery channel: the kind of recipient address.
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `credentials` *required*: `any`
        - description: Secret fields with their values masked (`***`); keys show what is set.
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `health_status`: `['string', 'null']`
        - description: `healthy` / `unhealthy` after the last test; `null` if never tested.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `last_checked_at`: `['integer', 'null']`
        - description: Unix milliseconds of the last test.
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for platform-owned providers.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `settings` *required*: `any`
        - description: Non-secret, transport-specific settings.
        - type: `any`
      - `transport` *required*: `string`
        - description: How a channel delivers.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/notification-providers/{id}`

- operationId: `update_notification_provider`
- summary: Update a notification provider.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `credentials`: `any`
      - description: Merged into the stored secrets; send `***` (or omit a key) to keep a
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `settings`: `any`
      - description: Replaces the settings document.
      - type: `any`
- responses:
  - `200`: Successfully updated provider
    - `application/json`:
      - type: `object (14 properties)`
      - `channel` *required*: `string`
        - description: A delivery channel: the kind of recipient address.
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `credentials` *required*: `any`
        - description: Secret fields with their values masked (`***`); keys show what is set.
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `health_status`: `['string', 'null']`
        - description: `healthy` / `unhealthy` after the last test; `null` if never tested.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `last_checked_at`: `['integer', 'null']`
        - description: Unix milliseconds of the last test.
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for platform-owned providers.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `settings` *required*: `any`
        - description: Non-secret, transport-specific settings.
        - type: `any`
      - `transport` *required*: `string`
        - description: How a channel delivers.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/notification-providers/{id}`

- operationId: `patch_notification_provider`
- summary: Update a notification provider (partial).
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `credentials`: `any`
      - description: Merged into the stored secrets; send `***` (or omit a key) to keep a
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_default`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `settings`: `any`
      - description: Replaces the settings document.
      - type: `any`
- responses:
  - `200`: Successfully updated provider
    - `application/json`:
      - type: `object (14 properties)`
      - `channel` *required*: `string`
        - description: A delivery channel: the kind of recipient address.
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `credentials` *required*: `any`
        - description: Secret fields with their values masked (`***`); keys show what is set.
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `health_status`: `['string', 'null']`
        - description: `healthy` / `unhealthy` after the last test; `null` if never tested.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `last_checked_at`: `['integer', 'null']`
        - description: Unix milliseconds of the last test.
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for platform-owned providers.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `settings` *required*: `any`
        - description: Non-secret, transport-specific settings.
        - type: `any`
      - `transport` *required*: `string`
        - description: How a channel delivers.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/notification-providers/{id}`

- operationId: `delete_notification_provider`
- summary: Delete a notification provider.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Successfully deleted provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/notification-providers/{id}/default`

- operationId: `set_default_notification_provider`
- summary: Make a provider the default for its owner and channel.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Provider is now the default
    - `application/json`:
      - type: `object (14 properties)`
      - `channel` *required*: `string`
        - description: A delivery channel: the kind of recipient address.
        - type: `string`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `credentials` *required*: `any`
        - description: Secret fields with their values masked (`***`); keys show what is set.
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `health_status`: `['string', 'null']`
        - description: `healthy` / `unhealthy` after the last test; `null` if never tested.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_default` *required*: `boolean`
        - type: `boolean`
      - `last_checked_at`: `['integer', 'null']`
        - description: Unix milliseconds of the last test.
        - type: `['integer', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id`: `['integer', 'null']`
        - description: `null` for platform-owned providers.
        - type: `['integer', 'null']`
      - `owner` *required*: `string`
        - description: Who owns a provider.
        - type: `string`
      - `settings` *required*: `any`
        - description: Non-secret, transport-specific settings.
        - type: `any`
      - `transport` *required*: `string`
        - description: How a channel delivers.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/notification-providers/{id}/test`

- operationId: `test_notification_provider`
- summary: Test a notification provider.
- tags: `Notification Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `recipient`: `['string', 'null']`
      - description: Email address to send the test message to (email channel). Defaults
      - type: `['string', 'null']`
- responses:
  - `200`: Test result
    - `application/json`:
      - type: `object (2 properties)`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Provider or organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/notifications`

- operationId: `list_notifications`
- summary: List the organization's notifications (the `kernel.notification`
collection).
- tags: `Notifications v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: One page of the organization's notifications
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid collection query (`urn:conusai:collections:*`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/notifications/_batch`

- operationId: `get_notifications_batch`
- summary: Read back notifications of the organization by id.
- tags: `Notifications v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible notifications among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/ocr/usage-breakdown`

- operationId: `getOcrUsageBreakdown`
- tags: `OCR v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Current-month OCR tiers, text layer, cache and spend
    - `application/json`:
      - type: `object (9 properties)`
      - `ai_ocr_budget`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `allowance_pages`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `cache_hit_ratio` *required*: `number`
        - type: `number`
      - `cache_hits` *required*: `string`
        - type: `string`
      - `cap_cents`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `current_spend_cents` *required*: `integer`
        - type: `integer`
      - `metered_pages` *required*: `string`
        - type: `string`
      - `text_layer_pages` *required*: `string`
        - type: `string`
      - `tiers` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Organization membership or metrics:read required

### `GET /v1/orgs/{org_slug}/orders`

- operationId: `list_orders`
- summary: List every ACME order of one organization.
- tags: `Domains v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: ACME orders in the organization
    - `application/json`:
      - type: `object (1 properties)`
      - `orders` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/projects`

- operationId: `list_org_projects`
- summary: List the projects in every workspace of the organization the caller can
see: all of them for an org Owner/Admin or a super-admin, otherwise the
workspaces the caller is a member of.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `cursor` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: One page of the organization's visible projects
    - `application/json`:
      - type: `object (3 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `next_cursor`: `['string', 'null']`
        - description: Pass as `cursor` for the next page; `null` on the last page
        - type: `['string', 'null']`
  - `400`: Invalid cursor or limit
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires projects:read)
  - `404`: Organization not found

### `GET /v1/orgs/{org_slug}/repositories`

- operationId: `list_synced_repositories`
- summary: List the synced repositories of one organization.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
  - `sort` (query): `string`
  - `direction` (query): `string`
  - `search` (query): `string`
  - `owner` (query): `string`
  - `language` (query): `string`
  - `private` (query): `boolean`
  - `git_provider_connection_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Synced repositories
    - `application/json`:
      - type: `object (2 properties)`
      - `repositories` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repositories/{owner}/{name}`

- operationId: `get_repository_by_name`
- summary: Read one repository by owner and name.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Repository found
    - `application/json`:
      - type: `object (15 properties)`
      - `clone_url`: `['string', 'null']`
        - description: HTTPS clone URL (e.g., <https://github.com/owner/repo.git>)
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `default_branch` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `full_name` *required*: `string`
        - type: `string`
      - `git_provider_connection_id` *required*: `integer`
        - description: ID of the git provider connection this repository was synced from.
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `language`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `preset`: `['array', 'null']`
        - type: `['array', 'null']`
      - `private` *required*: `boolean`
        - type: `boolean`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `ssh_url`: `['string', 'null']`
        - description: SSH clone URL (e.g., git@github.com:owner/repo.git)
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repositories/{owner}/{name}/all`

- operationId: `get_all_repositories_by_name`
- summary: Read every repository with one owner and name, across all providers.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Repositories found
    - `application/json`:
      - type: `array<object (15 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: No repositories found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repositories/{owner}/{name}/preset`

- operationId: `get_repository_preset_by_name`
- summary: Calculate the build preset for one repository, addressed by owner and name.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `name` (path) *required*: `string`
  - `branch` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Preset calculated
    - `application/json`:
      - type: `object (5 properties)`
      - `calculated_at` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `presets` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `repository_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repositories/{owner}/{repo}/branches`

- operationId: `get_repository_branches`
- summary: List one repository's branches, addressed by owner and repo.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `repo` (path) *required*: `string`
  - `connection_id` (query) *required*: `integer`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Branches
    - `application/json`:
      - type: `object (1 properties)`
      - `branches` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repositories/{owner}/{repo}/tags`

- operationId: `get_repository_tags`
- summary: List one repository's tags, addressed by owner and repo.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `owner` (path) *required*: `string`
  - `repo` (path) *required*: `string`
  - `connection_id` (query) *required*: `integer`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Tags
    - `application/json`:
      - type: `object (1 properties)`
      - `tags` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repository/{repository_id}`

- operationId: `get_repository_by_id`
- summary: Read one repository by id.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `repository_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Repository found
    - `application/json`:
      - type: `object (15 properties)`
      - `clone_url`: `['string', 'null']`
        - description: HTTPS clone URL (e.g., <https://github.com/owner/repo.git>)
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `default_branch` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `full_name` *required*: `string`
        - type: `string`
      - `git_provider_connection_id` *required*: `integer`
        - description: ID of the git provider connection this repository was synced from.
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `language`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `preset`: `['array', 'null']`
        - type: `['array', 'null']`
      - `private` *required*: `boolean`
        - type: `boolean`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `ssh_url`: `['string', 'null']`
        - description: SSH clone URL (e.g., git@github.com:owner/repo.git)
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repository/{repository_id}/branches`

- operationId: `get_branches_by_repository_id`
- summary: List one repository's branches, addressed by id.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `repository_id` (path) *required*: `integer`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Branches
    - `application/json`:
      - type: `object (1 properties)`
      - `branches` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repository/{repository_id}/commits`

- operationId: `list_commits_by_repository_id`
- summary: List one repository's commits.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `repository_id` (path) *required*: `integer`
  - `branch` (query) *required*: `string`
  - `per_page` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Commits
    - `application/json`:
      - type: `object (1 properties)`
      - `commits` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repository/{repository_id}/commits/{commit_sha}`

- operationId: `check_commit_exists`
- summary: Report whether one commit exists in one repository.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `repository_id` (path) *required*: `integer`
  - `commit_sha` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Commit lookup result
    - `application/json`:
      - type: `object (3 properties)`
      - `commit`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `commit_sha`: `['string', 'null']`
        - type: `['string', 'null']`
      - `exists` *required*: `boolean`
        - type: `boolean`
  - `400`: Malformed commit SHA
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/repository/{repository_id}/tags`

- operationId: `get_tags_by_repository_id`
- summary: List one repository's tags, addressed by id.
- tags: `Git Providers v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `repository_id` (path) *required*: `integer`
  - `fresh` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Tags
    - `application/json`:
      - type: `object (1 properties)`
      - `tags` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Repository not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/restore-runs/{id}`

- operationId: `get_restore_run`
- summary: Read the progress of one restore run.
- tags: `Restore v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Restore run progress
    - `application/json`:
      - type: `object (13 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `mode` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `recovery_target`: `any`
        - type: `any`
      - `source_backup_id` *required*: `integer`
        - type: `integer`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `target_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `target_service_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Restore run not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/revenue/metrics/global-mrr`

- operationId: `revenue_metrics_global_mrr`
- summary: Org-wide MRR, for a path-named organization.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `currency` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (4 properties)`
      - `change_percentage`: `['number', 'null']`
        - description: Percentage change vs 24h ago. Null when previous MRR is zero
        - type: `['number', 'null']`
      - `currency` *required*: `string`
        - type: `string`
      - `current_mrr_minor` *required*: `integer`
        - type: `integer`
      - `previous_mrr_minor` *required*: `integer`
        - description: MRR 24h before now, reconstructed from the event log.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found

### `GET /v1/orgs/{org_slug}/revenue/metrics/global-summary`

- operationId: `revenue_metrics_global_summary`
- summary: Org-wide revenue summary, for a path-named organization.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `currency` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (9 properties)`
      - `active_customers` *required*: `integer`
        - type: `integer`
      - `active_subscriptions` *required*: `integer`
        - type: `integer`
      - `currency` *required*: `string`
        - type: `string`
      - `current_mrr_minor` *required*: `integer`
        - type: `integer`
      - `paid_all_time_minor` *required*: `integer`
        - type: `integer`
      - `paid_last_30d_minor` *required*: `integer`
        - type: `integer`
      - `refunded_all_time_minor` *required*: `integer`
        - type: `integer`
      - `refunded_last_30d_minor` *required*: `integer`
        - type: `integer`
      - `transactions_last_30d` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/services/import`

- operationId: `import_service`
- summary: Adopt an already-running Docker container as a managed managed service.
- description: # Why this one stops at the organization

The legacy body calls `import_service_scoped`, which narrows by
`scope.organization_id()` and never reads a workspace. There is no workspace
predicate anywhere on that path, so a `{workspace_slug}` segment here would
be a segment the server never compares against anything — see the module
docs. The organization in the URL is the whole of the tenancy this route
enforces, and it is enforced: `org.active_org()` carries the organization
[`conusai_workspaces::path_scope::resolve_org_scope`] proved the caller is a
member of, and the legacy body's `org_scope_guard!` mints the service-layer
scope from it. A caller who names an organization they do not belong to
never reaches this function at all — the extractor 404s first.

# No `Path` extractor, deliberately

The URI captures exactly one parameter, `{org_slug}`, and it is consumed by
the scope extractor. Adding a bare `Path<String>` here would bind that slug
as if it were a resource identifier — it compiles, registers and answers
200 with the wrong meaning. `path_arity_tests::a_bare_path_string_swallows_the_org_slug`
pins that hazard rather than leaving it as prose.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `container_id` *required*: `string`
      - description: Container ID or name to import
      - type: `string`
    - `name` *required*: `string`
      - description: Name to register the service as in `ConusAI`
      - type: `string`
    - `parameters` *required*: `object`
      - description: Service configuration parameters
      - type: `object`
    - `service_type` *required*: `string`
      - type: `string`
    - `version`: `['string', 'null']`
      - description: Optional version override
      - type: `['string', 'null']`
- responses:
  - `201`: Service imported successfully
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization not found for this caller
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/services/{id}/restore`

- operationId: `start_restore`
- summary: Start a restore into one managed service.
- tags: `Restore v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `202`: Restore run started
    - `application/json`:
      - type: `object (13 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `mode` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `recovery_target`: `any`
        - type: `any`
      - `source_backup_id` *required*: `integer`
        - type: `integer`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `target_service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `target_service_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Backup or service not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/services/{id}/restore-capabilities`

- operationId: `get_restore_capabilities`
- summary: Read the restore capabilities one managed service declares.
- tags: `Restore v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Capabilities declared by the service
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Service not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/services/{id}/restore-plan`

- operationId: `plan_restore`
- summary: Preview what a restore would do, without performing it.
- tags: `Restore v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `any`
- responses:
  - `200`: Preview of what the restore will do
    - `application/json`:
      - type: `object (9 properties)`
      - `destructive` *required*: `boolean`
        - description: Whether any step overwrites existing data on the target service.
        - type: `boolean`
      - `engine` *required*: `string`
        - description: Target engine ("postgres", etc.).
        - type: `string`
      - `errors` *required*: `array<string>`
        - description: Blocking problems. The UI disables the Start button when non-empty.
        - type: `array<string>`
      - `mode` *required*: `string`
        - description: Echo of the requested mode for the UI.
        - type: `string`
      - `source_backup` *required*: `object (7 properties)`
        - type: `object (7 properties)`
      - `steps` *required*: `array<string>`
        - description: Ordered list of human-readable actions the orchestrator will take.
        - type: `array<string>`
      - `strategy` *required*: `string`
        - description: How the restore will be performed: `"walg_restore"`, `"pg_dump_restore"`,
        - type: `string`
      - `target_service` *required*: `object (3 properties)`
        - type: `object (3 properties)`
      - `warnings` *required*: `array<string>`
        - description: Non-blocking caveats the user should see (cross-service, empty
        - type: `array<string>`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Backup or service not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/services/{id}/restore-runs`

- operationId: `list_restore_runs_for_service`
- summary: List the recent restore runs of one managed service.
- tags: `Restore v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Recent restore runs for the service
    - `application/json`:
      - type: `array<object (13 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Service not found in this organization
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/services/{service_id}/git/admin-password/rotate`

- operationId: `rotate_git_admin_password`
- summary: Replace a Git service's admin password. Needs a browser session with a
fresh step-up.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The new password, shown once
    - `application/json`:
      - type: `object (3 properties)`
      - `password` *required*: `string`
        - description: The new password. The previous one has stopped working.
        - type: `string`
      - `rotated_at` *required*: `string`
        - type: `string`
      - `username` *required*: `string`
        - description: The admin login the password belongs to.
        - type: `string`
  - `401`: Authenticated browser session required
  - `403`: Not a workspace admin, or a credential that can never do this
  - `404`: No such Git service in this organization
  - `409`: The service is not running
  - `428`: Fresh session verification required
  - `500`: The password was not rotated, or its audit failed

### `GET /v1/orgs/{org_slug}/services/{service}/readiness`

- operationId: `service_readiness`
- tags: `Release inventory`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `service` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: This organization's safe service prerequisites; unknown never grants admission
    - `application/json`:
      - type: `object (14 properties)`
      - `actual_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `desired_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `desired_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `facts` *required*: `object (9 properties)`
        - type: `object (9 properties)`
      - `id` *required*: `string`
        - description: Stable service id, or opaque `managed:<row id>`; never a customer name.
        - type: `string`
      - `installed_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_transition`: `['string', 'null']`
        - type: `['string', 'null']`
      - `mode` *required*: `string`
        - type: `string`
      - `observed_at` *required*: `string`
        - type: `string`
      - `observed_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `reason_codes` *required*: `array<string>`
        - type: `array<string>`
      - `recorded_release_evidence`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `registry_ready` *required*: `string`
        - type: `string`
      - `schema_ledger_digest`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Organization or service unavailable, including foreign organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Prerequisite observations unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/session/active-workspace`

- operationId: `get_active_workspace`
- summary: Read this session's active workspace, scoped to one organization by path.
- description: The legacy `/v1/session/active-workspace` returns `null` whenever the
session has no usable workspace scope, because without a path org there is
no tenant boundary to violate. The path-scoped route names an organization,
so a workspace scope that belongs to a different organization is reported
absent (404) instead of being silently masked as `null`. The validation
itself reuses [`crate::scope::validate_workspace_scope`], the same function
the legacy switch handler uses.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The session's current workspace scope in this organization
    - `application/json`:
      - type: `object (4 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: The organization the workspace above belongs to, echoed so a client can
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
      - `workspace_id`: `string | null`
        - type: `string | null`
  - `401`: Unauthorized
  - `404`: Organization not found, or the active workspace is not in this organization

### `PUT /v1/orgs/{org_slug}/session/active-workspace`

- operationId: `set_active_workspace`
- summary: Switch this session to a workspace in one organization, scoped by path.
- description: Delegates to the legacy handler with an `ActiveOrg` built from the resolved
path scope, so the access validation and the session write are the same
instructions as on the legacy route.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `workspace_id` *required*: `string`
      - description: Identifies a workspace, which belongs to exactly one organization.
      - type: `string`
- responses:
  - `200`: Session switched
    - `application/json`:
      - type: `object (4 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: The organization the workspace above belongs to, echoed so a client can
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
      - `workspace_id`: `string | null`
        - type: `string | null`
  - `400`: Credential is not a browser session
  - `401`: Unauthorized
  - `404`: No such workspace, or the caller cannot reach it in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/mcp-servers`

- operationId: `list_global_mcps`
- summary: List an organization's global MCP server definitions.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Global MCP server definitions
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/settings/mcp-servers`

- operationId: `create_global_mcp`
- summary: Create a global MCP server definition in an organization.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `config` *required*: `object`
      - type: `object`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
- responses:
  - `201`: MCP server created
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/mcp-servers/{slug}`

- operationId: `get_global_mcp`
- summary: Read one global MCP server definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: MCP server definition
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: MCP server not found in this organization
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/settings/mcp-servers/{slug}`

- operationId: `update_global_mcp`
- summary: Replace one global MCP server definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `config` *required*: `object`
      - type: `object`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: MCP server updated
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: MCP server not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/settings/mcp-servers/{slug}`

- operationId: `delete_global_mcp`
- summary: Delete one global MCP server definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: MCP server deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: MCP server not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/secrets`

- operationId: `list_secrets`
- summary: List an organization's agent secrets. Values are always masked.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Agent secrets for the organization, values masked
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/settings/secrets`

- operationId: `upsert_secret`
- summary: Create or replace one agent secret in an organization.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `mount_path`: `['string', 'null']`
      - description: Required for "file" type secrets — absolute path inside the sandbox
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `secret_type`: `string`
      - description: "env" (environment variable) or "file" (written to `mount_path`)
      - type: `string`
    - `value` *required*: `string`
      - type: `string`
- responses:
  - `201`: Secret created or updated, value masked
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `mount_path`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `secret_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `value` *required*: `string`
        - description: Always masked in responses
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/settings/secrets/{name}`

- operationId: `delete_secret`
- summary: Delete one agent secret by name.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Secret deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Secret not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/skills`

- operationId: `list_global_skills`
- summary: List an organization's global skill definitions.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Global skill definitions for the organization
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/settings/skills`

- operationId: `create_global_skill`
- summary: Create a global skill definition in an organization.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `content` *required*: `string`
      - type: `string`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
- responses:
  - `201`: Skill created
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/settings/skills/upload`

- operationId: `upload_global_skill`
- summary: Upload a global skill with a tar.gz archive.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `multipart/form-data`:
    - type: `string`
- responses:
  - `201`: Skill uploaded
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/skills/{slug}`

- operationId: `get_global_skill`
- summary: Read one global skill definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Skill definition
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Skill not found in this organization
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/settings/skills/{slug}`

- operationId: `update_global_skill`
- summary: Replace one global skill definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `content`: `['string', 'null']`
      - type: `['string', 'null']`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Skill updated
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Skill not found in this organization
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/settings/skills/{slug}`

- operationId: `delete_global_skill`
- summary: Delete one global skill definition.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Skill deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Skill not found in this organization
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/settings/skills/{slug}/archive`

- operationId: `download_global_skill_archive`
- summary: Download a global skill's tar.gz archive.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Skill archive tar.gz
    - `application/gzip`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Skill not found in this organization, or has no archive
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/spending-cap`

- operationId: `get_spending_cap`
- summary: Read one organization's spending cap.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `cap_behavior` *required*: `string`
        - type: `string`
      - `spending_cap_monthly_minor`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/spending-cap`

- operationId: `update_spending_cap`
- summary: Update one organization's spending cap.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `cap_behavior`: `['string', 'null']`
      - type: `['string', 'null']`
    - `spending_cap_monthly_minor`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `cap_behavior` *required*: `string`
        - type: `string`
      - `spending_cap_monthly_minor`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/sso/domains`

- operationId: `list_org_sso_domains`
- summary: List an organization's SSO domains.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `domains` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/sso/domains`

- operationId: `create_org_sso_domain`
- summary: Add an SSO domain to an organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `domain` *required*: `string`
      - type: `string`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (9 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `domain` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_checked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `txt_challenge` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verified_at`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/sso/domains/{domain_id}`

- operationId: `delete_org_sso_domain`
- summary: Delete an organization's SSO domain.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: No Content
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/sso/domains/{domain_id}/verify`

- operationId: `verify_org_sso_domain`
- summary: Verify an organization's SSO domain via its TXT challenge.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (9 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `domain` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_checked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `txt_challenge` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verified_at`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/sso/enforcement`

- operationId: `update_org_sso_enforcement`
- summary: Toggle SSO enforcement for an organization.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `sso_enforced` *required*: `boolean`
      - type: `boolean`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (16 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_theme`: `any`
        - type: `any`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `logo_blob_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `plan_key`: `['string', 'null']`
        - type: `['string', 'null']`
      - `quota_max_containers`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_disk_mb`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `quota_max_projects`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/sso/providers`

- operationId: `list_org_sso_providers`
- summary: List an organization's SSO providers.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (1 properties)`
      - `providers` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/sso/providers`

- operationId: `create_org_sso_provider`
- summary: Create an org-owned SSO provider.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `client_id` *required*: `string`
      - type: `string`
    - `client_secret` *required*: `string`
      - type: `string`
    - `default_role`: `string`
      - type: `string`
    - `enabled`: `boolean`
      - type: `boolean`
    - `group_claim`: `string`
      - type: `string`
    - `issuer_url` *required*: `string`
      - type: `string`
    - `jit_provisioning`: `boolean`
      - type: `boolean`
    - `name` *required*: `string`
      - type: `string`
    - `role_claim`: `string`
      - type: `string`
    - `scopes`: `string`
      - type: `string`
    - `template`: `string`
      - type: `string`
    - `trust_idp_email`: `boolean`
      - description: Defaults false. Set to true only for `IdPs` where an admin
      - type: `boolean`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (13 properties)`
      - `client_id` *required*: `string`
        - type: `string`
      - `client_secret` *required*: `string`
        - description: Always masked — the secret is never returned after creation.
        - type: `string`
      - `default_role` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `group_claim` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `issuer_url` *required*: `string`
        - type: `string`
      - `jit_provisioning` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role_claim` *required*: `string`
        - type: `string`
      - `scopes` *required*: `string`
        - type: `string`
      - `template` *required*: `string`
        - type: `string`
      - `trust_idp_email` *required*: `boolean`
        - description: When true, the resolver skips the `email_verified` claim gate
        - type: `boolean`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/sso/providers/{provider_id}`

- operationId: `get_org_sso_provider`
- summary: Read one org-owned SSO provider.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (13 properties)`
      - `client_id` *required*: `string`
        - type: `string`
      - `client_secret` *required*: `string`
        - description: Always masked — the secret is never returned after creation.
        - type: `string`
      - `default_role` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `group_claim` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `issuer_url` *required*: `string`
        - type: `string`
      - `jit_provisioning` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role_claim` *required*: `string`
        - type: `string`
      - `scopes` *required*: `string`
        - type: `string`
      - `template` *required*: `string`
        - type: `string`
      - `trust_idp_email` *required*: `boolean`
        - description: When true, the resolver skips the `email_verified` claim gate
        - type: `boolean`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/sso/providers/{provider_id}`

- operationId: `update_org_sso_provider`
- summary: Update one org-owned SSO provider.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `client_id`: `['string', 'null']`
      - type: `['string', 'null']`
    - `client_secret`: `['string', 'null']`
      - type: `['string', 'null']`
    - `default_role`: `['string', 'null']`
      - type: `['string', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `group_claim`: `['string', 'null']`
      - type: `['string', 'null']`
    - `issuer_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `jit_provisioning`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `role_claim`: `['string', 'null']`
      - type: `['string', 'null']`
    - `scopes`: `['string', 'null']`
      - type: `['string', 'null']`
    - `template`: `['string', 'null']`
      - type: `['string', 'null']`
    - `trust_idp_email`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (13 properties)`
      - `client_id` *required*: `string`
        - type: `string`
      - `client_secret` *required*: `string`
        - description: Always masked — the secret is never returned after creation.
        - type: `string`
      - `default_role` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `group_claim` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `issuer_url` *required*: `string`
        - type: `string`
      - `jit_provisioning` *required*: `boolean`
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `role_claim` *required*: `string`
        - type: `string`
      - `scopes` *required*: `string`
        - type: `string`
      - `template` *required*: `string`
        - type: `string`
      - `trust_idp_email` *required*: `boolean`
        - description: When true, the resolver skips the `email_verified` claim gate
        - type: `boolean`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Conflict
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/sso/providers/{provider_id}`

- operationId: `delete_org_sso_provider`
- summary: Delete one org-owned SSO provider.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `provider_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: No Content
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/tools`

- operationId: `listAiTools`
- summary: List the organization's tools. `ai_tools:read`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The organization's tools
    - `application/json`:
      - type: `object (2 properties)`
      - `catalog_version` *required*: `integer`
        - description: The organization's catalog version the list was read at.
        - type: `integer`
      - `tools` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:read)
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/tools`

- operationId: `publishAiTool`
- summary: Publish a tool version. The same canonical JSON twice is one version
(200, `created: false`); a new version of an existing tool waits for
approval. `ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `manifest`: `object`
      - description: The platform manifest (owner, `version`, scopes, idempotency, timeout,
      - type: `object`
    - `namespace` *required*: `string`
      - description: 1 to 64 of `[a-z0-9_-]`.
      - type: `string`
    - `risk_class` *required*: `string`
      - description: `read` | `write` | `destructive` | `external_send`.
      - type: `string`
    - `tool` *required*: `object`
      - description: The MCP Tool (revision 2026-07-28): `name`, `description`,
      - type: `object`
- responses:
  - `200`: The version already existed
    - `application/json`:
      - type: `object (5 properties)`
      - `approval_state` *required*: `string`
        - type: `string`
      - `catalog_version` *required*: `integer`
        - type: `integer`
      - `content_hash` *required*: `string`
        - type: `string`
      - `created` *required*: `boolean`
        - description: `false` when the same canonical JSON was already published.
        - type: `boolean`
      - `tool_id` *required*: `integer`
        - type: `integer`
  - `201`: A new version was published
    - `application/json`:
      - type: `object (5 properties)`
      - `approval_state` *required*: `string`
        - type: `string`
      - `catalog_version` *required*: `integer`
        - type: `integer`
      - `content_hash` *required*: `string`
        - type: `string`
      - `created` *required*: `boolean`
        - description: `false` when the same canonical JSON was already published.
        - type: `boolean`
      - `tool_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization not found
  - `422`: The tool or manifest is malformed

### `GET /v1/orgs/{org_slug}/tools/connections`

- operationId: `listMcpConnections`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (8 properties)>`

### `POST /v1/orgs/{org_slug}/tools/connections`

- operationId: `createMcpConnection`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `credential`: `any`
      - description: Write-only `{kind:bearer,token}` or `{kind:client_credentials,token_url,client_id,client_secret,scope?,resource?}`.
      - type: `any`
    - `namespace` *required*: `string`
      - type: `string`
    - `server_url` *required*: `string`
      - type: `string`
    - `ttl_seconds`: `integer`
      - type: `integer`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (8 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `has_credential` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_sync_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_synced_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `namespace` *required*: `string`
        - type: `string`
      - `server_url` *required*: `string`
        - type: `string`
      - `ttl_seconds` *required*: `integer`
        - type: `integer`

### `PATCH /v1/orgs/{org_slug}/tools/connections/{connection_id}`

- operationId: `updateMcpConnection`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `clear_credential`: `boolean`
      - type: `boolean`
    - `credential`: `any`
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `ttl_seconds`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (8 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `has_credential` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_sync_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_synced_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `namespace` *required*: `string`
        - type: `string`
      - `server_url` *required*: `string`
        - type: `string`
      - `ttl_seconds` *required*: `integer`
        - type: `integer`

### `DELETE /v1/orgs/{org_slug}/tools/connections/{connection_id}`

- operationId: `deleteMcpConnection`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: No Content

### `POST /v1/orgs/{org_slug}/tools/connections/{connection_id}/sync`

- operationId: `syncMcpConnection`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `connection_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `published` *required*: `integer`
        - type: `integer`
      - `quarantined` *required*: `array<string>`
        - type: `array<string>`
      - `unchanged` *required*: `integer`
        - type: `integer`

### `POST /v1/orgs/{org_slug}/tools/import/mcp`

- operationId: `importMcpTools`
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `namespace` *required*: `string`
      - type: `string`
    - `server_url` *required*: `string`
      - description: Public HTTPS MCP endpoint. Credentials, fragments and query strings are forbidden.
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `published` *required*: `integer`
        - type: `integer`
      - `quarantined` *required*: `array<string>`
        - type: `array<string>`
      - `unchanged` *required*: `integer`
        - type: `integer`
  - `403`: Requires ai_tools:write
  - `422`: Invalid connection
  - `502`: Upstream unavailable

### `GET /v1/orgs/{org_slug}/tools/{tool_id}`

- operationId: `getAiTool`
- summary: One tool with its versions and bindings. `ai_tools:read`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The tool
    - `application/json`:
      - type: `object (5 properties)`
      - `bindings` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `read_confirmation`: `object (4 properties) | null`
        - type: `object (4 properties) | null`
      - `readiness`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `tool` *required*: `object (7 properties)`
        - type: `object (7 properties)`
      - `versions` *required*: `array<object (9 properties)>`
        - description: Newest first.
        - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:read)
  - `404`: Organization or tool not found

### `PATCH /v1/orgs/{org_slug}/tools/{tool_id}`

- operationId: `updateAiTool`
- summary: Set a tool's state. `ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `state` *required*: `string`
      - description: `active` | `disabled` | `quarantined`.
      - type: `string`
- responses:
  - `204`: State changed
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization or tool not found
  - `422`: Unknown state

### `DELETE /v1/orgs/{org_slug}/tools/{tool_id}`

- operationId: `deleteAiTool`
- summary: Delete a tool with its versions and bindings. `ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Deleted
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization or tool not found

### `POST /v1/orgs/{org_slug}/tools/{tool_id}/bindings`

- operationId: `bindAiTool`
- summary: Bind a tool to the organization, a project or an environment.
`ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `always_on`: `boolean`
      - type: `boolean`
    - `content_hash`: `['string', 'null']`
      - description: A pinned version; exactly one of this and `version_req`.
      - type: `['string', 'null']`
    - `enabled`: `boolean`
      - type: `boolean`
    - `environment_id`: `['integer', 'null']`
      - description: Only together with `project_id`.
      - type: `['integer', 'null']`
    - `project_id`: `['integer', 'null']`
      - description: Omitted: the whole organization.
      - type: `['integer', 'null']`
    - `version_req`: `['string', 'null']`
      - description: A requirement on the manifest `version`, such as `^1.2`.
      - type: `['string', 'null']`
- responses:
  - `201`: Bound
    - `application/json`:
      - type: `object (1 properties)`
      - `binding_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization, tool, version, project or environment not found
  - `409`: The tool is already bound at that scope, or the pinned version is not approved
  - `422`: Not exactly one version selector

### `PATCH /v1/orgs/{org_slug}/tools/{tool_id}/bindings/{binding_id}`

- operationId: `updateAiToolBinding`
- summary: Enable or disable a binding. `ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
  - `binding_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `enabled` *required*: `boolean`
      - type: `boolean`
- responses:
  - `204`: Updated
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization, tool or binding not found

### `PUT /v1/orgs/{org_slug}/tools/{tool_id}/read-confirmation`

- operationId: `confirmAiToolRead`
- summary: Confirm that the current version of an `mcp` tool only reads.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `content_hash` *required*: `string`
      - description: The tool's current approved version, 64 lower-case hex characters.
      - type: `string`
- responses:
  - `200`: Confirmed: the executor treats this version as read
    - `application/json`:
      - type: `object (4 properties)`
      - `confirmed_at` *required*: `string`
        - type: `string`
      - `confirmed_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `content_hash` *required*: `string`
        - description: The only version the confirmation applies to.
        - type: `string`
      - `tool_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Only an organization owner or admin, in person
  - `404`: Organization, tool or version not found
  - `409`: Not the current approved version of an mcp tool raised to external_send
  - `422`: Invalid content hash

### `DELETE /v1/orgs/{org_slug}/tools/{tool_id}/read-confirmation`

- operationId: `revokeAiToolRead`
- summary: Withdraw a tool's read confirmation: it is `external_send` again.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Revoked (or there was none)
  - `401`: Unauthorized
  - `403`: Only an organization owner or admin, in person
  - `404`: Organization or tool not found

### `POST /v1/orgs/{org_slug}/tools/{tool_id}/versions/{content_hash}/decision`

- operationId: `decideAiToolVersion`
- summary: Approve or reject a version waiting for approval. `ai_tools:write`.
- tags: `AI Tools`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `tool_id` (path) *required*: `integer`
  - `content_hash` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `decision` *required*: `string`
      - description: `approved` | `rejected`.
      - type: `string`
- responses:
  - `204`: Decided
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires ai_tools:write)
  - `404`: Organization, tool or version not found
  - `409`: The version is not waiting for approval
  - `422`: The decision is not approved or rejected

### `POST /v1/orgs/{org_slug}/transfer-ownership`

- operationId: `transfer_ownership`
- summary: Transfer organization ownership to another member.
- tags: `Organizations v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `target_user_id` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `email_verified`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_sso`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `mfa_enabled`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `org_role` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `user_email`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_id` *required*: `integer`
        - type: `integer`
      - `user_name`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/usage/ai-ocr-budget`

- operationId: `getAiOcrBudgetV1`
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The organization's AI+OCR budget and status
    - `application/json`:
      - type: `object (2 properties)`
      - `budget`: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `status`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `503`: A cost cannot be converted (missing FX rate)

### `PUT /v1/orgs/{org_slug}/usage/ai-ocr-budget`

- operationId: `setAiOcrBudgetV1`
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `currency` *required*: `string`
      - description: ISO-4217 alphabetic code, e.g. `EUR`. AI (USD) and OCR (EUR) supplier
      - type: `string`
    - `margin_bps`: `['integer', 'null']`
      - description: Margin over supplier cost in basis points (1500 = 15%). Platform
      - type: `['integer', 'null']`
    - `monthly_budget_minor` *required*: `integer`
      - description: Monthly budget in minor units (cents) of `currency`; `10000` is 100.00.
      - type: `integer`
- responses:
  - `200`: Budget set
    - `application/json`:
      - type: `object (6 properties)`
      - `currency` *required*: `string`
        - description: ISO-4217 alphabetic code, e.g. `EUR`.
        - type: `string`
      - `margin_bps` *required*: `integer`
        - description: Margin on supplier cost in basis points (1500 = 15%).
        - type: `integer`
      - `monthly_budget_minor` *required*: `integer`
        - description: Monthly budget in minor units (cents) of `currency`.
        - type: `integer`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `updated_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid budget
  - `401`: Unauthorized
  - `403`: Not an owner or admin, or margin_bps set by a non-platform-admin
  - `404`: Organization not found

### `DELETE /v1/orgs/{org_slug}/usage/ai-ocr-budget`

- operationId: `clearAiOcrBudgetV1`
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Budget cleared (or there was none)
  - `401`: Unauthorized
  - `403`: Not an owner or admin
  - `404`: Organization not found

### `GET /v1/orgs/{org_slug}/usage/allowances`

- operationId: `usageAllowances`
- summary: Current-cycle allowance status for one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Current cycle allowance status
    - `application/json`:
      - type: `object (7 properties)`
      - `allowances` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `cap_behavior` *required*: `string`
        - description: The org's cap-overrun behavior (`"block"` or `"overage"`) at the time
        - type: `string`
      - `cycle_end` *required*: `string`
        - type: `string`
      - `cycle_start` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `plan_key` *required*: `string`
        - type: `string`
      - `total_overage_cents` *required*: `integer`
        - description: Sum of `overage_cents` across all metrics -- the amount this cycle's
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/cap-verdict`

- operationId: `usageCapVerdict`
- summary: Spend-cap verdict for one metric of one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `metric` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Cap verdict for a metric
    - `application/json`:
      - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/export.csv`

- operationId: `exportUsageCsv`
- summary: CSV export of one organization's current-cycle hourly usage.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: CSV export of current-cycle hourly usage
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/projection`

- operationId: `usageProjection`
- summary: End-of-cycle quantity projection for one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: End-of-cycle quantity projection
    - `application/json`:
      - type: `object (4 properties)`
      - `cycle_end` *required*: `string`
        - type: `string`
      - `cycle_start` *required*: `string`
        - type: `string`
      - `metrics` *required*: `object`
        - type: `object`
      - `organization_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/projects`

- operationId: `usageProjectBreakdown`
- summary: Per-project usage breakdown for one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Per-project usage breakdown
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/series`

- operationId: `usageSeries`
- summary: Hourly usage series for one metric of one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `metric` (query) *required*: `string`
  - `start` (query) *required*: `string`
  - `end` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Hourly usage series
    - `application/json`:
      - type: `array<object (4 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/spend-cap`

- operationId: `usageSpendCap`
- summary: Projected cycle spend against the organization's monthly spending cap.
- description: \[conusai\] Loop 12 Phase 3: the path-scoped twin of
`/usage/spend-cap`. It is an org-tier route for the same reason every other
route in this module is: `MeteringService::spend_cap_status` takes a single
`organization_id` and the cap itself lives on the `organizations` row.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Projected cycle spend against the org's cap, with its currency, and the AI+OCR budget
    - `application/json`:
      - type: `object (6 properties)`
      - `ai_ocr_budget`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `cap_cents`: `['integer', 'null']`
        - description: The all-scope cap (`spending_cap_monthly_minor`), `null` = uncapped.
        - type: `['integer', 'null']`
      - `cap_currency` *required*: `string`
        - description: The all-scope cap's declared currency: the `billing_rates` currency,
        - type: `string`
      - `capped` *required*: `boolean`
        - description: The all-scope cap is reached under `cap_behavior = "block"`.
        - type: `boolean`
      - `current_spend_cents` *required*: `integer`
        - description: Projected all-scope spend in integer cents of `cap_currency`.
        - type: `integer`
      - `organization_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/summary`

- operationId: `usageSummary`
- summary: Current-cycle usage summary for one organization.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Current cycle summary
    - `application/json`:
      - type: `object (4 properties)`
      - `cycle_end` *required*: `string`
        - type: `string`
      - `cycle_start` *required*: `string`
        - type: `string`
      - `metrics` *required*: `object`
        - type: `object`
      - `organization_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/usage/workspaces`

- operationId: `usageWorkspaceBreakdown`
- summary: Per-workspace usage breakdown for one organization.
- description: Org tier despite the name: the answer is one row per workspace *of this
organization*, so the organization is the scope being proven.
- tags: `Usage v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Per-workspace usage breakdown
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/vpn/clients`

- operationId: `vpn_list_clients`
- summary: List the organization's devices. `vpn:read`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Registered devices
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/vpn/clients`

- operationId: `vpnRegisterClient`
- summary: Register a device from the console. `vpn:write`. Idempotent by public
key: re-POSTing the same key returns the same tunnel IP.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `name` *required*: `string`
      - description: Operator-facing device name, e.g. `alice-macbook`.
      - type: `string`
    - `public_key` *required*: `string`
      - description: `WireGuard` public key, base64 (32 bytes). The private half never
      - type: `string`
- responses:
  - `200`: Client registered; the PSK is shown once
    - `application/json`:
      - type: `object (7 properties)`
      - `allowed_ips` *required*: `array<string>`
        - description: Split-tunnel destinations: the origin host's /32 plus the subnets the
        - type: `array<string>`
      - `anchor_endpoint` *required*: `string`
        - description: Public endpoint of the anchor's `wg-clients` interface, `host:port`.
        - type: `string`
      - `anchor_public_key` *required*: `string`
        - description: Public key of the anchor's `wg-clients` interface.
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `persistent_keepalive` *required*: `integer`
        - description: Required behind NAT (spec §5c: without it the tunnel goes quiet).
        - type: `integer`
      - `psk`: `['string', 'null']`
        - description: The per-peer PSK — present ONLY on the creating call, never re-emitted.
        - type: `['string', 'null']`
      - `tunnel_ip` *required*: `string`
        - description: The client's tunnel address, always a /32.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `409`: No anchor paired / anchor predates client VPN
  - `422`: Validation error

### `DELETE /v1/orgs/{org_slug}/vpn/clients/{id}`

- operationId: `vpn_revoke_client`
- summary: Revoke a device: the peer is removed from the LIVE interface first, then
the row is marked (spec §8). If the anchor is unreachable this answers
502 and the row is NOT marked — a peer revoked in the UI but still on
the interface reads as safe, which is worse than no revocation.
`vpn:write`. Cross-org ids 404.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Client revoked
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_handshake_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `revoked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `tunnel_ip` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Client not found

### `POST /v1/orgs/{org_slug}/vpn/clients/{id}/rotate-key`

- operationId: `vpnRotateKey`
- summary: Rotate a device's key with a two-key overlap (spec §8): the old key
stays live for the grace window while the new one enrols, so the session
does not drop. Returns the new key's registration response — its PSK is
shown once. `vpn:write`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `public_key` *required*: `string`
      - description: The device's NEW `WireGuard` public key, base64 (32 bytes) —
      - type: `string`
- responses:
  - `200`: Key rotated; the new PSK is shown once
    - `application/json`:
      - type: `object (7 properties)`
      - `allowed_ips` *required*: `array<string>`
        - description: Split-tunnel destinations: the origin host's /32 plus the subnets the
        - type: `array<string>`
      - `anchor_endpoint` *required*: `string`
        - description: Public endpoint of the anchor's `wg-clients` interface, `host:port`.
        - type: `string`
      - `anchor_public_key` *required*: `string`
        - description: Public key of the anchor's `wg-clients` interface.
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `persistent_keepalive` *required*: `integer`
        - description: Required behind NAT (spec §5c: without it the tunnel goes quiet).
        - type: `integer`
      - `psk`: `['string', 'null']`
        - description: The per-peer PSK — present ONLY on the creating call, never re-emitted.
        - type: `['string', 'null']`
      - `tunnel_ip` *required*: `string`
        - description: The client's tunnel address, always a /32.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Client not found
  - `422`: Validation error

### `GET /v1/orgs/{org_slug}/vpn/enrollment-tokens`

- operationId: `vpnListEnrollmentTokens`
- summary: List the organization's enrolment tokens. `vpn:read`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Enrollment tokens (hashes never included)
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/vpn/enrollment-tokens`

- operationId: `vpnMintEnrollmentToken`
- summary: Mint an enrolment token. `vpn:write`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `label` *required*: `string`
      - description: Operator-facing name, e.g. `fleet-2026-08`.
      - type: `string`
    - `single_use`: `['boolean', 'null']`
      - description: Default true. Multi-use is an explicit fleet-enrolment opt-in.
      - type: `['boolean', 'null']`
    - `ttl_secs`: `['integer', 'null']`
      - description: TTL in seconds. Default 900 (15 min); ceiling 86400 (24h).
      - type: `['integer', 'null']`
- responses:
  - `200`: Token minted; the raw token is shown once
    - `application/json`:
      - type: `object (5 properties)`
      - `expires_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `label` *required*: `string`
        - type: `string`
      - `single_use` *required*: `boolean`
        - type: `boolean`
      - `token` *required*: `string`
        - description: Shown once. Never stored, never logged, never recoverable.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: Validation error

### `DELETE /v1/orgs/{org_slug}/vpn/enrollment-tokens/{id}`

- operationId: `vpnRevokeEnrollmentToken`
- summary: Revoke an enrolment token. `vpn:write`. Cross-org ids 404.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Token revoked
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `expires_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `label` *required*: `string`
        - type: `string`
      - `redeemed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `revoked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `single_use` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Token not found

### `GET /v1/orgs/{org_slug}/vpn/grants`

- operationId: `vpn_list_grants`
- summary: List the organization's grants. `vpn:read`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Grants
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/vpn/grants`

- operationId: `vpnCreateGrant`
- summary: Create a grant. `vpn:write`.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `dst_cidr` *required*: `string`
      - description: Destination CIDR, or a host (masked to its /32). `0.0.0.0/0` is
      - type: `string`
    - `port` *required*: `integer`
      - description: 1–65535. Port ranges are a later spec change, not a silent array.
      - type: `integer`
    - `principal_id` *required*: `string`
      - description: `users.id` as text, or the org role name.
      - type: `string`
    - `principal_kind` *required*: `string`
      - description: `user` | `org_role`.
      - type: `string`
    - `proto` *required*: `string`
      - description: `tcp` | `udp`.
      - type: `string`
- responses:
  - `200`: Grant created
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `dst_cidr` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `port` *required*: `integer`
        - type: `integer`
      - `principal_id` *required*: `string`
        - type: `string`
      - `principal_kind` *required*: `string`
        - type: `string`
      - `proto` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization not found
  - `422`: Validation error

### `DELETE /v1/orgs/{org_slug}/vpn/grants/{id}`

- operationId: `vpnDeleteGrant`
- summary: Delete a grant (hard delete; the audit log is the history). `vpn:write`.
Cross-org ids 404.
- tags: `VPN`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Grant deleted
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by` *required*: `integer`
        - type: `integer`
      - `dst_cidr` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `port` *required*: `integer`
        - type: `integer`
      - `principal_id` *required*: `string`
        - type: `string`
      - `principal_kind` *required*: `string`
        - type: `string`
      - `proto` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Grant not found

### `GET /v1/orgs/{org_slug}/workspaces`

- operationId: `list_workspaces`
- summary: List the workspaces of one organization.
- description: This is the first handler in the codebase to take
[`crate::path_scope::OrgScope`]. The type has existed since the extractor
landed and had zero handler uses: every org-level route went through
`ActiveOrg` instead, which is why the org tier became unreachable for
session callers when 2.2b removed the header.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Workspaces in the organization
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `404`: Organization not found

### `POST /v1/orgs/{org_slug}/workspaces`

- operationId: `create_workspace`
- summary: Create a workspace in one organization.
- description: The organization comes from the path, never from the body: a request body
cannot place a workspace into another tenant.

Delegates to the flat handler with an `ActiveOrg` built from the resolved
path scope, so the guard (`organizations:update`) and the audit row of the
owner grant are the same instructions on both routes.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
- responses:
  - `201`: Workspace created
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: The caller's organization role lacks `organizations:update`
  - `404`: Organization not found

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}`

- operationId: `get_workspace`
- summary: Read one workspace.
- description: No `workspace_guard!` call appears below. That macro answers "may this
caller act in the workspace named by the header, inside the org named by
the header?"; [`WorkspaceScope`]'s extractor has already answered the same
question from the path, in a single JOIN, before this body runs. Calling it
again would re-derive a scope that is already proven.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Workspace details
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Workspace not found in this organization

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}`

- operationId: `update_workspace`
- summary: Rename or re-describe one workspace.
- description: `WorkspaceService::update_workspace` checks the Admin floor and the
operation's `OrganizationsUpdate` permission itself. `scope.tenant()`
carries both the role resolved by the JOIN and any custom-key permission
ceiling, so neither check is dropped in the move off the header.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Workspace updated
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - description: Identifies a workspace, which belongs to exactly one organization.
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient workspace role
  - `404`: Workspace not found in this organization

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}`

- operationId: `delete_workspace`
- summary: Delete one workspace.
- description: `WorkspaceService::delete_workspace` requires the Owner tier, because the
delete cascades to every project in the workspace.
- tags: `Workspaces v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Workspace deleted, with every project in it
  - `401`: Unauthorized
  - `403`: Insufficient workspace role
  - `404`: Workspace not found in this organization
  - `409`: Workspace delete refused, nothing deleted: tenant audit rows hold the workspace or a project in it (`https://conusai.com/probs/audit-retention-blocks-delete`); the workspace still owns managed services, Git provider connections, backup schedules, sandboxes or schedule runs, or still contains projects with no project eraser registered (`https://conusai.com/probs/workspace-delete-blocked`); or a project in it refused its delete (`https://conusai.com/probs/project-delete-blocked`, e.g. guide usage awaiting delivery to metering, or a container of any of its projects could not be removed: every project's containers are stopped before the first project is erased)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: A project's delete failed after every check passed (`https://conusai.com/probs/project-delete-failed`; the projects deleted before it are gone and the workspace remains), or a database error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/backups/schedule-runs/{id}/jobs`

- operationId: `list_schedule_run_jobs`
- summary: List the individual backup jobs of one scheduler run.
- description: The only workspace-tier operation in this module. `list_schedule_run_jobs_scoped`
narrows on `workspaces.id` in addition to `organizations.id`, so unlike every
other route here it has a workspace predicate to apply — and both scopes are
therefore resolved from the URL. The two extractors run independently: the
[`OrgScope`] one supplies the org role that `org_scope_guard!` checks inside
the legacy body, which [`PathWorkspaceScope`] does not carry (it carries a
*workspace* role), and the [`PathWorkspaceScope`] one supplies the tenant
scope the service filters on.
- tags: `Backups v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Jobs for this scheduler run
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/dashboard/projects-analytics`

- operationId: `get_dashboard_projects_analytics`
- summary: Batched dashboard analytics for several projects of one workspace.
- description: This one stays at the **workspace** rung rather than the project rung,
because its whole purpose is to answer for a list of projects in a single
round trip. The `project_ids` query parameter therefore survives — but the
workspace it is evaluated against is now the URL's, not a header's, and the
legacy body still runs `assert_project_in_scope` for every id in the list.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_ids` (query) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved batch analytics
    - `application/json`:
      - type: `object (1 properties)`
      - `projects` *required*: `object`
        - description: Map of `project_id` -> analytics data
        - type: `object`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: A requested project is not in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/monitors-health/projects`

- operationId: `get_projects_monitor_health`
- summary: Monitor-health summaries for several projects of one workspace.
- description: The batch is rejected whole when any requested project is outside the
resolved workspace, rather than silently filtered: a caller enumerating
`project_ids` must not be able to distinguish "foreign project" from "no
health data" by noticing which ids disappeared from the response.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Health summaries per project
    - `application/json`:
      - type: `object (1 properties)`
      - `projects` *required*: `object`
        - type: `object`
  - `400`: Invalid parameters
  - `401`: Unauthorized
  - `404`: Workspace not found, or a project outside it was requested
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects`

- operationId: `list_projects`
- summary: List the projects of one workspace (the `kernel.project` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Projects in the workspace
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (28 properties)>`
        - type: `array<object (28 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid collection query (`urn:conusai:collections:*`)
  - `401`: Unauthorized
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects`

- operationId: `create_project`
- summary: Create a project in this workspace.
- description: The owning organization and workspace come from the path. The legacy route
takes the workspace from `workspace_id` in the **body**, which is how a
project could be created in a workspace the caller merely named; here the
body field is ignored entirely.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (25 properties)`
    - `automatic_deploy`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `build_command`: `['string', 'null']`
      - type: `['string', 'null']`
    - `custom_domain`: `['string', 'null']`
      - type: `['string', 'null']`
    - `directory` *required*: `string`
      - type: `string`
    - `environment_variables`: `['array', 'null']`
      - type: `['array', 'null']`
    - `exposed_port`: `['integer', 'null']`
      - description: Port exposed by the container (fallback when image has no EXPOSE directive)
      - type: `['integer', 'null']`
    - `git_provider_connection_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `git_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `install_command`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_on_demand`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_public_repo`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_web_app`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `main_branch` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `output_dir`: `['string', 'null']`
      - type: `['string', 'null']`
    - `performance_metrics_enabled`: `boolean`
      - type: `boolean`
    - `preset` *required*: `string`
      - type: `string`
    - `preset_config`: `object (2 properties) | object | object (4 properties) | null`
      - type: `object (2 properties) | object | object (4 properties) | null`
    - `project_type`: `['string', 'null']`
      - type: `['string', 'null']`
    - `repo_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `repo_owner`: `['string', 'null']`
      - type: `['string', 'null']`
    - `source_type`: `string`
      - description: Source type for project deployments
      - type: `string`
    - `storage_service_ids` *required*: `array<integer>`
      - type: `array<integer>`
    - `use_default_wildcard`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `workspace_id`: `string | null`
      - type: `string | null`
- responses:
  - `200`: Project created
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `403`: Forbidden, or the organization's project limit is reached
  - `404`: Organization or workspace not found
  - `409`: Project limit exceeded
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/_batch`

- operationId: `get_projects_batch`
- summary: Read back projects of this workspace by id.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible projects among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (28 properties)>`
        - type: `array<object (28 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/by-slug/{slug}`

- operationId: `get_project_by_slug`
- summary: Look one project up by its slug within this workspace.
- description: # Why this coexists with `GET {PROJECT_SCOPE_PREFIX}`

The two resolve the same row: `{project_slug}` *is* the slug. They are kept
as separate operations because the legacy surface has them as separate
operations, and the migration's contract is that every legacy operation
gains a twin a client can move to one-for-one. A console calling
`GET /api/projects/by-slug/{slug}` today gets a v1 URL with the same shape
and the same response, rather than having to be rewritten onto a
differently-shaped route at the same time as it is moved onto the path
grammar.

`by-slug` is a literal at the `{project_slug}` position, so it is reserved:
see [`COLLECTION_LITERALS`].
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Project details
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/from-template`

- operationId: `create_project_from_template`
- summary: Create a project in this workspace from a template.
- description: `from-template` is a literal at the `{project_slug}` position — see
[`COLLECTION_LITERALS`].
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (10 properties)`
    - `automatic_deploy`: `boolean`
      - description: Enable automatic deployment on push (defaults to true). Only honoured in
      - type: `boolean`
    - `environment_variables`: `array<object (2 properties)>`
      - description: Environment variables to set (key-value pairs)
      - type: `array<object (2 properties)>`
    - `git_provider_connection_id`: `['integer', 'null']`
      - description: Git provider connection ID. When omitted, the project deploys directly
      - type: `['integer', 'null']`
    - `private`: `boolean`
      - description: Whether to make the repository private (defaults to true)
      - type: `boolean`
    - `project_name` *required*: `string`
      - description: Name for the new project
      - type: `string`
    - `repository_name`: `['string', 'null']`
      - description: Name for the new repository to create. Required in fork mode; ignored in
      - type: `['string', 'null']`
    - `repository_owner`: `['string', 'null']`
      - description: Owner/organization for the new repository (defaults to authenticated user)
      - type: `['string', 'null']`
    - `storage_service_ids`: `array<integer>`
      - description: External storage service IDs to attach to the project
      - type: `array<integer>`
    - `template_slug` *required*: `string`
      - description: Template slug to use as the base
      - type: `string`
    - `workspace_id`: `string | null`
      - type: `string | null`
- responses:
  - `201`: Project created from the template
    - `application/json`:
      - type: `object (6 properties)`
      - `message` *required*: `string`
        - description: Message with additional info
        - type: `string`
      - `project_id` *required*: `integer`
        - description: ID of the created project
        - type: `integer`
      - `project_name` *required*: `string`
        - description: Name of the created project
        - type: `string`
      - `project_slug` *required*: `string`
        - description: Slug of the created project
        - type: `string`
      - `repository_url` *required*: `string`
        - description: URL of the created repository
        - type: `string`
      - `template_slug` *required*: `string`
        - description: Template that was used
        - type: `string`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `403`: Forbidden, or the organization's project limit is reached
  - `404`: Template, organization or workspace not found
  - `409`: Project limit exceeded
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/statistics`

- operationId: `project_statistics`
- summary: Project statistics for this workspace.
- description: `statistics` is a literal at the `{project_slug}` position — see
[`COLLECTION_LITERALS`].
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Project statistics for the workspace
    - `application/json`:
      - type: `object (1 properties)`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}`

- operationId: `get_project`
- summary: Read one project.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Project details
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}`

- operationId: `update_project`
- summary: Update one project.
- description: The organization and workspace come from the path, never from the body: a
request body cannot move a project into another tenant.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (25 properties)`
    - `automatic_deploy`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `build_command`: `['string', 'null']`
      - type: `['string', 'null']`
    - `custom_domain`: `['string', 'null']`
      - type: `['string', 'null']`
    - `directory` *required*: `string`
      - type: `string`
    - `environment_variables`: `['array', 'null']`
      - type: `['array', 'null']`
    - `exposed_port`: `['integer', 'null']`
      - description: Port exposed by the container (fallback when image has no EXPOSE directive)
      - type: `['integer', 'null']`
    - `git_provider_connection_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `git_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `install_command`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_on_demand`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_public_repo`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `is_web_app`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `main_branch` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `output_dir`: `['string', 'null']`
      - type: `['string', 'null']`
    - `performance_metrics_enabled`: `boolean`
      - type: `boolean`
    - `preset` *required*: `string`
      - type: `string`
    - `preset_config`: `object (2 properties) | object | object (4 properties) | null`
      - type: `object (2 properties) | object | object (4 properties) | null`
    - `project_type`: `['string', 'null']`
      - type: `['string', 'null']`
    - `repo_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `repo_owner`: `['string', 'null']`
      - type: `['string', 'null']`
    - `source_type`: `string`
      - description: Source type for project deployments
      - type: `string`
    - `storage_service_ids` *required*: `array<integer>`
      - type: `array<integer>`
    - `use_default_wildcard`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `workspace_id`: `string | null`
      - type: `string | null`
- responses:
  - `200`: Project updated
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}`

- operationId: `delete_project`
- summary: Delete one project.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Project deleted
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found in this workspace
  - `409`: Project delete refused, nothing deleted: retained tool approval/action history holds it (problem type `https://conusai.com/probs/audit-retention-blocks-delete`), or `https://conusai.com/probs/project-delete-blocked` while guide usage awaits delivery to metering or a container of the project could not be removed; retry later
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/active-visitors`

- operationId: `get_active_visitors`
- summary: Active visitors right now, for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved active visitors
    - `application/json`:
      - type: `object (2 properties)`
      - `active_visitors` *required*: `integer`
        - type: `integer`
      - `window_minutes` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agent-egress-policy`

- operationId: `get_egress_policy`
- summary: The project's agent egress policy (empty when none is set).
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Hosts agent runs in this project may reach when their definition names them
    - `application/json`:
      - type: `object (3 properties)`
      - `allowed_hosts` *required*: `array<string>`
        - type: `array<string>`
      - `updated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agent-egress-policy`

- operationId: `set_egress_policy`
- summary: Replace the project's agent egress policy.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `allowed_hosts` *required*: `array<string>`
      - description: Exact host names (no scheme, port, path or wildcard), at most 64.
      - type: `array<string>`
- responses:
  - `200`: Policy replaced
    - `application/json`:
      - type: `object (3 properties)`
      - `allowed_hosts` *required*: `array<string>`
        - type: `array<string>`
      - `updated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `updated_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid host
  - `401`: Unauthorized
  - `403`: Requires SettingsWrite and the organization Owner or Admin role
  - `404`: Project not found

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents`

- operationId: `list_agents`
- summary: List a project's agents.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Agents for the project
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (33 properties)>`
        - type: `array<object (33 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents`

- operationId: `create_agent`
- summary: Create an agent in a project.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (25 properties)`
    - `ai_model`: `['string', 'null']`
      - description: Preferred model identifier for the CLI. `Some("")` clears the stored value.
      - type: `['string', 'null']`
    - `ai_provider`: `['string', 'null']`
      - type: `['string', 'null']`
    - `ai_provider_key_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `api_key`: `['string', 'null']`
      - description: Plain-text API key — will be encrypted before storage
      - type: `['string', 'null']`
    - `branch_prefix`: `['string', 'null']`
      - type: `['string', 'null']`
    - `config_repo_branch`: `['string', 'null']`
      - description: Branch of the config repo to use (default: "main").
      - type: `['string', 'null']`
    - `config_repo_url`: `['string', 'null']`
      - description: Private config repo containing .claude/ directory (skills, MCP, plugins).
      - type: `['string', 'null']`
    - `cooldown_minutes`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `daily_budget_minor`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `deliverable`: `['string', 'null']`
      - type: `['string', 'null']`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `egress_config`: `any`
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `max_turns`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `mcp_servers_config`: `any`
      - description: MCP servers config (Claude Code settings.json mcpServers format).
      - type: `any`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `prompt`: `['string', 'null']`
      - type: `['string', 'null']`
    - `sandbox_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `secrets_config`: `any`
      - description: Explicit secret names; omitted or [] injects no organization secrets.
      - type: `any`
    - `skills_config`: `any`
      - description: Skills config as JSON array.
      - type: `any`
    - `slug`: `['string', 'null']`
      - type: `['string', 'null']`
    - `timeout_seconds`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `tools_config`: `any`
      - description: Inline tools as a JSON array, or an object with `tools` and runner policy.
      - type: `any`
    - `trigger_config`: `any`
      - description: Trigger configuration JSON: { "error": { "`new_issue"`: true, "regression": true }, "manual": true }
      - type: `any`
    - `verify_config`: `any`
      - type: `any`
- responses:
  - `201`: Agent created
    - `application/json`:
      - type: `object (33 properties)`
      - `ai_model`: `['string', 'null']`
        - description: Preferred model for the CLI (e.g. "sonnet", "gpt-5-codex"). `None` means default.
        - type: `['string', 'null']`
      - `ai_provider` *required*: `string`
        - type: `string`
      - `ai_provider_key_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `api_key_set` *required*: `boolean`
        - description: `true` if an API key is set; `false` otherwise.
        - type: `boolean`
      - `branch_prefix` *required*: `string`
        - type: `string`
      - `config_repo_branch`: `['string', 'null']`
        - description: Branch of the config repo to use.
        - type: `['string', 'null']`
      - `config_repo_url`: `['string', 'null']`
        - description: Private config repo containing .claude/ directory (skills, MCP, plugins).
        - type: `['string', 'null']`
      - `cooldown_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `daily_budget_minor` *required*: `integer`
        - type: `integer`
      - `deliverable` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `egress_config`: `any`
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `execution_auth_mode` *required*: `string`
        - description: Authoritative runtime auth route; subscription inference is outside gateway policy.
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `max_turns` *required*: `integer`
        - type: `integer`
      - `mcp_servers_config`: `any`
        - description: MCP servers config (Claude Code settings.json mcpServers format).
        - type: `any`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt`: `['string', 'null']`
        - type: `['string', 'null']`
      - `sandbox_enabled` *required*: `boolean`
        - description: Whether runs of this agent execute in the sandbox.
        - type: `boolean`
      - `secrets_config`: `any`
        - type: `any`
      - `skills_config`: `any`
        - description: Skills config as JSON array.
        - type: `any`
      - `slug` *required*: `string`
        - type: `string`
      - `source` *required*: `string`
        - type: `string`
      - `timeout_seconds` *required*: `integer`
        - type: `integer`
      - `tools_config`: `any`
        - description: Tools config as JSON array.
        - type: `any`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verify_config`: `any`
        - type: `any`
      - `webhook_token`: `['string', 'null']`
        - description: Secret token for the `X-Webhook-Token` header. Shown once when created,
        - type: `['string', 'null']`
      - `webhook_url`: `['string', 'null']`
        - description: Public webhook URL for triggering this agent externally.
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/cli-status`

- operationId: `get_cli_status`
- summary: Whether the selected AI CLI is installed where agents run.
- description: The body reports on the host, not the project — but the project segment is
still resolved and still has to belong to the named workspace, so this route
is scoped where its legacy twin is not.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `provider` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: CLI status
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/definitions/validate`

- operationId: `validate_agent_definition`
- summary: Validate an agent definition (the text of a `.conusai/agents/<slug>.md`
file) with the parser a deployment uses. Stores nothing.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `definition` *required*: `string`
      - description: The definition file's text: YAML frontmatter between `---` lines, then
      - type: `string`
    - `slug` *required*: `string`
      - description: The agent's slug: the file stem of `.conusai/agents/<slug>.md`.
      - type: `string`
- responses:
  - `200`: The verdict: `valid`, every problem in `errors`, unresolvable references in `warnings`
    - `application/json`:
      - type: `object (4 properties)`
      - `errors` *required*: `array<object (3 properties)>`
        - description: Every problem that makes the definition invalid.
        - type: `array<object (3 properties)>`
      - `normalized`: `['string', 'null']`
        - description: The definition with every default written out, when valid.
        - type: `['string', 'null']`
      - `valid` *required*: `boolean`
        - description: Whether a deployment would accept the definition.
        - type: `boolean`
      - `warnings` *required*: `array<object (3 properties)>`
        - description: References this project cannot resolve (an MCP server or skill slug
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs`

- operationId: `list_all_runs`
- summary: List every agent run in a project.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Agent runs for the project
    - `application/json`:
      - type: `object (4 properties)`
      - `items` *required*: `array<object (35 properties)>`
        - type: `array<object (35 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs`

- operationId: `run_agent_definition`
- summary: Start an ephemeral run from an inline agent definition (the text of a
`.conusai/agents/<slug>.md` file). Nothing is committed and no agent is
stored; the run's limits are clamped and its deliverable is `report`.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `cpu_limit`: `['number', 'null']`
      - description: CPU cores for the sandbox, overriding `limits.cpu_limit` (clamped).
      - type: `['number', 'null']`
    - `definition` *required*: `string`
      - description: The definition file's text. The server validates it, clamps its limits,
      - type: `string`
    - `error_group_id`: `['integer', 'null']`
      - description: Optional error group to link the run to. The prompt then receives
      - type: `['integer', 'null']`
    - `memory_limit_mb`: `['integer', 'null']`
      - description: Sandbox memory in MB, overriding `limits.memory_limit_mb` (clamped).
      - type: `['integer', 'null']`
    - `slug` *required*: `string`
      - description: The slug the run is recorded under: the file stem of
      - type: `string`
    - `user_context`: `['string', 'null']`
      - description: Optional context appended to the prompt (e.g. "test against staging
      - type: `['string', 'null']`
- responses:
  - `202`: Ephemeral run created and queued
    - `application/json`:
      - type: `object (35 properties)`
      - `agent_name`: `['string', 'null']`
        - description: Name of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `agent_slug`: `['string', 'null']`
        - description: Slug of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `ai_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_output`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_provider`: `['string', 'null']`
        - description: AI provider slug that executed this run (e.g. `claude_cli`, `codex_cli`, opencode).
        - type: `['string', 'null']`
      - `ai_reasoning`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_session_id`: `['string', 'null']`
        - description: Claude CLI session UUID for resuming conversations via `--resume`.
        - type: `['string', 'null']`
      - `analysis`: `['string', 'null']`
        - description: Report / analysis text produced by the agent (used for report/notification deliverables).
        - type: `['string', 'null']`
      - `branch_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_sha`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `ephemeral_definition`: `['string', 'null']`
        - description: The definition an ephemeral run executed, as `.md` text with every
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `estimated_cost_minor` *required*: `integer`
        - type: `integer`
      - `files_changed` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `phase`: `['string', 'null']`
        - description: Autofixer phase: "analyzing", "analyzed", "fixing", `"fix_ready"`, `"no_fix"`,
        - type: `['string', 'null']`
      - `pr_number`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `pr_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preview_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt_text`: `['string', 'null']`
        - description: Final assembled prompt the AI CLI actually saw (trigger context block +
        - type: `['string', 'null']`
      - `provenance`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `run_config`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `source` *required*: `string`
        - description: `committed` (the run's config lives in `project_agents`) or
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tokens_input` *required*: `integer`
        - type: `integer`
      - `tokens_output` *required*: `integer`
        - type: `integer`
      - `trigger_source_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `trigger_source_ref`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_source_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `user_context`: `['string', 'null']`
        - description: User-provided context for this run (e.g. webhook payload, manual instructions).
        - type: `['string', 'null']`
  - `400`: Invalid definition or oversized payload; `errors` lists each problem with its field and line
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/latest-for-source`

- operationId: `latest_run_for_source`
- summary: Latest run for a given trigger source.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `trigger_source_type` (query) *required*: `string`
  - `trigger_source_id` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Latest matching run, or null if none
    - `application/json`:
      - type: `object (35 properties) | null`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/{run_id}`

- operationId: `get_run_with_logs`
- summary: One run with its logs.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Run with logs
    - `application/json`:
      - type: `object (2 properties)`
      - `logs` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `run` *required*: `object (35 properties)`
        - type: `object (35 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/{run_id}/cancel`

- operationId: `cancel_run`
- summary: Cancel a running run.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Run cancelled
    - `application/json`:
      - type: `object (35 properties)`
      - `agent_name`: `['string', 'null']`
        - description: Name of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `agent_slug`: `['string', 'null']`
        - description: Slug of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `ai_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_output`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_provider`: `['string', 'null']`
        - description: AI provider slug that executed this run (e.g. `claude_cli`, `codex_cli`, opencode).
        - type: `['string', 'null']`
      - `ai_reasoning`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_session_id`: `['string', 'null']`
        - description: Claude CLI session UUID for resuming conversations via `--resume`.
        - type: `['string', 'null']`
      - `analysis`: `['string', 'null']`
        - description: Report / analysis text produced by the agent (used for report/notification deliverables).
        - type: `['string', 'null']`
      - `branch_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_sha`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `ephemeral_definition`: `['string', 'null']`
        - description: The definition an ephemeral run executed, as `.md` text with every
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `estimated_cost_minor` *required*: `integer`
        - type: `integer`
      - `files_changed` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `phase`: `['string', 'null']`
        - description: Autofixer phase: "analyzing", "analyzed", "fixing", `"fix_ready"`, `"no_fix"`,
        - type: `['string', 'null']`
      - `pr_number`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `pr_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preview_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt_text`: `['string', 'null']`
        - description: Final assembled prompt the AI CLI actually saw (trigger context block +
        - type: `['string', 'null']`
      - `provenance`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `run_config`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `source` *required*: `string`
        - description: `committed` (the run's config lives in `project_agents`) or
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tokens_input` *required*: `integer`
        - type: `integer`
      - `tokens_output` *required*: `integer`
        - type: `integer`
      - `trigger_source_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `trigger_source_ref`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_source_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `user_context`: `['string', 'null']`
        - description: User-provided context for this run (e.g. webhook payload, manual instructions).
        - type: `['string', 'null']`
  - `400`: Run is already in a terminal state
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/{run_id}/events`

- operationId: `stream_agent_run_events`
- summary: Replay an AG-UI run's events after an offset, then follow it live.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `string`
  - `offset` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: AG-UI Server-Sent Events after the offset, then the live tail; no model call
    - `text/event-stream`:
      - type: `any`
  - `400`: Invalid offset (urn:conusai:agents:offset-invalid)
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Run not found (urn:conusai:agents:run-not-found)
  - `410`: Offset expired (urn:conusai:agents:offset-expired)

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/{run_id}/reports`

- operationId: `report_agent_run_v1`
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `message` *required*: `string`
      - type: `string`
- responses:
  - `204`: No Content
  - `403`: Forbidden
  - `404`: Not Found

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/runs/{run_id}/retry`

- operationId: `retry_run`
- summary: Retry a finished run with the same trigger context.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: New run created from retry
    - `application/json`:
      - type: `object (35 properties)`
      - `agent_name`: `['string', 'null']`
        - description: Name of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `agent_slug`: `['string', 'null']`
        - description: Slug of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `ai_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_output`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_provider`: `['string', 'null']`
        - description: AI provider slug that executed this run (e.g. `claude_cli`, `codex_cli`, opencode).
        - type: `['string', 'null']`
      - `ai_reasoning`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_session_id`: `['string', 'null']`
        - description: Claude CLI session UUID for resuming conversations via `--resume`.
        - type: `['string', 'null']`
      - `analysis`: `['string', 'null']`
        - description: Report / analysis text produced by the agent (used for report/notification deliverables).
        - type: `['string', 'null']`
      - `branch_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_sha`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `ephemeral_definition`: `['string', 'null']`
        - description: The definition an ephemeral run executed, as `.md` text with every
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `estimated_cost_minor` *required*: `integer`
        - type: `integer`
      - `files_changed` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `phase`: `['string', 'null']`
        - description: Autofixer phase: "analyzing", "analyzed", "fixing", `"fix_ready"`, `"no_fix"`,
        - type: `['string', 'null']`
      - `pr_number`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `pr_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preview_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt_text`: `['string', 'null']`
        - description: Final assembled prompt the AI CLI actually saw (trigger context block +
        - type: `['string', 'null']`
      - `provenance`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `run_config`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `source` *required*: `string`
        - description: `committed` (the run's config lives in `project_agents`) or
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tokens_input` *required*: `integer`
        - type: `integer`
      - `tokens_output` *required*: `integer`
        - type: `integer`
      - `trigger_source_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `trigger_source_ref`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_source_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `user_context`: `['string', 'null']`
        - description: User-provided context for this run (e.g. webhook payload, manual instructions).
        - type: `['string', 'null']`
  - `400`: Run is still active
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/sandbox-status`

- operationId: `get_sandbox_status`
- summary: Sandbox readiness for the project's agents. See [`get_cli_status`] on why
the project segment matters even though the body ignores it.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Sandbox readiness (Docker + agent image)
    - `application/json`:
      - type: `object (5 properties)`
      - `docker_available` *required*: `boolean`
        - type: `boolean`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `firecracker_available` *required*: `boolean`
        - type: `boolean`
      - `image_name` *required*: `string`
        - type: `string`
      - `image_ready` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/smoke-test`

- operationId: `smoke_test_agent`
- summary: Smoke-test the AI CLI in the environment agents actually run in. See
[`get_cli_status`] on why the project segment matters here.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `provider_id` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Smoke test result
    - `application/json`:
      - type: `object (8 properties)`
      - `auth_info`: `['string', 'null']`
        - description: Auth email / method
        - type: `['string', 'null']`
      - `cli_authenticated` *required*: `boolean`
        - description: Claude CLI authenticated?
        - type: `boolean`
      - `cli_installed` *required*: `boolean`
        - description: Claude CLI installed?
        - type: `boolean`
      - `cli_version`: `['string', 'null']`
        - description: Claude CLI version
        - type: `['string', 'null']`
      - `detail`: `['string', 'null']`
        - description: Full output for debugging
        - type: `['string', 'null']`
      - `environment` *required*: `string`
        - description: Where the test ran: "host" or "sandbox"
        - type: `string`
      - `passed` *required*: `boolean`
        - description: Whether the smoke test passed
        - type: `boolean`
      - `setup_hint`: `['string', 'null']`
        - description: What the user needs to do if the test failed
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}`

- operationId: `get_agent`
- summary: Get one agent by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Agent config
    - `application/json`:
      - type: `object (33 properties)`
      - `ai_model`: `['string', 'null']`
        - description: Preferred model for the CLI (e.g. "sonnet", "gpt-5-codex"). `None` means default.
        - type: `['string', 'null']`
      - `ai_provider` *required*: `string`
        - type: `string`
      - `ai_provider_key_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `api_key_set` *required*: `boolean`
        - description: `true` if an API key is set; `false` otherwise.
        - type: `boolean`
      - `branch_prefix` *required*: `string`
        - type: `string`
      - `config_repo_branch`: `['string', 'null']`
        - description: Branch of the config repo to use.
        - type: `['string', 'null']`
      - `config_repo_url`: `['string', 'null']`
        - description: Private config repo containing .claude/ directory (skills, MCP, plugins).
        - type: `['string', 'null']`
      - `cooldown_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `daily_budget_minor` *required*: `integer`
        - type: `integer`
      - `deliverable` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `egress_config`: `any`
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `execution_auth_mode` *required*: `string`
        - description: Authoritative runtime auth route; subscription inference is outside gateway policy.
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `max_turns` *required*: `integer`
        - type: `integer`
      - `mcp_servers_config`: `any`
        - description: MCP servers config (Claude Code settings.json mcpServers format).
        - type: `any`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt`: `['string', 'null']`
        - type: `['string', 'null']`
      - `sandbox_enabled` *required*: `boolean`
        - description: Whether runs of this agent execute in the sandbox.
        - type: `boolean`
      - `secrets_config`: `any`
        - type: `any`
      - `skills_config`: `any`
        - description: Skills config as JSON array.
        - type: `any`
      - `slug` *required*: `string`
        - type: `string`
      - `source` *required*: `string`
        - type: `string`
      - `timeout_seconds` *required*: `integer`
        - type: `integer`
      - `tools_config`: `any`
        - description: Tools config as JSON array.
        - type: `any`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verify_config`: `any`
        - type: `any`
      - `webhook_token`: `['string', 'null']`
        - description: Secret token for the `X-Webhook-Token` header. Shown once when created,
        - type: `['string', 'null']`
      - `webhook_url`: `['string', 'null']`
        - description: Public webhook URL for triggering this agent externally.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or agent not found in this workspace

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}`

- operationId: `update_agent`
- summary: Update an agent by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (25 properties)`
    - `ai_model`: `['string', 'null']`
      - description: Preferred model identifier for the CLI. `Some("")` clears the stored value.
      - type: `['string', 'null']`
    - `ai_provider`: `['string', 'null']`
      - type: `['string', 'null']`
    - `ai_provider_key_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `api_key`: `['string', 'null']`
      - description: Plain-text API key — will be encrypted before storage
      - type: `['string', 'null']`
    - `branch_prefix`: `['string', 'null']`
      - type: `['string', 'null']`
    - `config_repo_branch`: `['string', 'null']`
      - description: Branch of the config repo to use (default: "main").
      - type: `['string', 'null']`
    - `config_repo_url`: `['string', 'null']`
      - description: Private config repo containing .claude/ directory (skills, MCP, plugins).
      - type: `['string', 'null']`
    - `cooldown_minutes`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `daily_budget_minor`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `deliverable`: `['string', 'null']`
      - type: `['string', 'null']`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `egress_config`: `any`
      - type: `any`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `max_turns`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `mcp_servers_config`: `any`
      - description: MCP servers config (Claude Code settings.json mcpServers format).
      - type: `any`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `prompt`: `['string', 'null']`
      - type: `['string', 'null']`
    - `sandbox_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `secrets_config`: `any`
      - description: Explicit secret names; omitted or [] injects no organization secrets.
      - type: `any`
    - `skills_config`: `any`
      - description: Skills config as JSON array.
      - type: `any`
    - `slug`: `['string', 'null']`
      - type: `['string', 'null']`
    - `timeout_seconds`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `tools_config`: `any`
      - description: Inline tools as a JSON array, or an object with `tools` and runner policy.
      - type: `any`
    - `trigger_config`: `any`
      - description: Trigger configuration JSON: { "error": { "`new_issue"`: true, "regression": true }, "manual": true }
      - type: `any`
    - `verify_config`: `any`
      - type: `any`
- responses:
  - `200`: Agent updated
    - `application/json`:
      - type: `object (33 properties)`
      - `ai_model`: `['string', 'null']`
        - description: Preferred model for the CLI (e.g. "sonnet", "gpt-5-codex"). `None` means default.
        - type: `['string', 'null']`
      - `ai_provider` *required*: `string`
        - type: `string`
      - `ai_provider_key_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `api_key_set` *required*: `boolean`
        - description: `true` if an API key is set; `false` otherwise.
        - type: `boolean`
      - `branch_prefix` *required*: `string`
        - type: `string`
      - `config_repo_branch`: `['string', 'null']`
        - description: Branch of the config repo to use.
        - type: `['string', 'null']`
      - `config_repo_url`: `['string', 'null']`
        - description: Private config repo containing .claude/ directory (skills, MCP, plugins).
        - type: `['string', 'null']`
      - `cooldown_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `daily_budget_minor` *required*: `integer`
        - type: `integer`
      - `deliverable` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `egress_config`: `any`
        - type: `any`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `execution_auth_mode` *required*: `string`
        - description: Authoritative runtime auth route; subscription inference is outside gateway policy.
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `max_turns` *required*: `integer`
        - type: `integer`
      - `mcp_servers_config`: `any`
        - description: MCP servers config (Claude Code settings.json mcpServers format).
        - type: `any`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt`: `['string', 'null']`
        - type: `['string', 'null']`
      - `sandbox_enabled` *required*: `boolean`
        - description: Whether runs of this agent execute in the sandbox.
        - type: `boolean`
      - `secrets_config`: `any`
        - type: `any`
      - `skills_config`: `any`
        - description: Skills config as JSON array.
        - type: `any`
      - `slug` *required*: `string`
        - type: `string`
      - `source` *required*: `string`
        - type: `string`
      - `timeout_seconds` *required*: `integer`
        - type: `integer`
      - `tools_config`: `any`
        - description: Tools config as JSON array.
        - type: `any`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `updated_at` *required*: `string`
        - type: `string`
      - `verify_config`: `any`
        - type: `any`
      - `webhook_token`: `['string', 'null']`
        - description: Secret token for the `X-Webhook-Token` header. Shown once when created,
        - type: `['string', 'null']`
      - `webhook_url`: `['string', 'null']`
        - description: Public webhook URL for triggering this agent externally.
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or agent not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}`

- operationId: `delete_agent`
- summary: Delete an agent by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Agent deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or agent not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/runs`

- operationId: `list_agent_runs`
- summary: List one agent's runs.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Runs for the agent
    - `application/json`:
      - type: `object (4 properties)`
      - `items` *required*: `array<object (35 properties)>`
        - type: `array<object (35 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or agent not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/runs`

- operationId: `start_agent_run`
- summary: Start an AG-UI run of an agent and stream its events.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object`
- responses:
  - `200`: AG-UI Server-Sent Events; RUN_STARTED carries conusaiRunId
    - `text/event-stream`:
      - type: `any`
  - `400`: Malformed input (urn:conusai:agents:input-invalid)
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or resume without a browser session (urn:conusai:agents:resume-requires-session)
  - `404`: Project or agent not found in this workspace
  - `409`: Stale interrupt (urn:conusai:agents:interrupt-stale)

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/secret-grants`

- operationId: `list_secret_grants`
- summary: List the organization secrets granted to one agent in a project.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Secret names granted to the agent (never values)
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `400`: Invalid agent slug
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/secret-grants/{secret_name}`

- operationId: `grant_secret`
- summary: Grant one organization secret to one agent in a project (idempotent).
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
  - `secret_name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Secret granted
    - `application/json`:
      - type: `object (5 properties)`
      - `agent_slug` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `granted_by_user_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `secret_name` *required*: `string`
        - type: `string`
  - `400`: Invalid agent slug or secret name
  - `401`: Unauthorized
  - `403`: Requires SettingsWrite and the organization Owner or Admin role
  - `404`: Project or secret not found

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/secret-grants/{secret_name}`

- operationId: `revoke_secret`
- summary: Revoke one agent secret grant.
- tags: `Secrets v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
  - `secret_name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Grant revoked
  - `401`: Unauthorized
  - `403`: Requires SettingsWrite and the organization Owner or Admin role
  - `404`: Project or grant not found

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/agents/{slug}/trigger`

- operationId: `trigger_agent`
- summary: Trigger an agent run.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `trigger_source_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `trigger_source_ref`: `['string', 'null']`
      - description: Support conversation UUID; never sent to the coding agent as credentials or transcript data.
      - type: `['string', 'null']`
    - `trigger_source_type`: `['string', 'null']`
      - type: `['string', 'null']`
    - `user_context`: `['string', 'null']`
      - description: Optional context from the user (e.g. a research topic, bug description, or instructions).
      - type: `['string', 'null']`
- responses:
  - `202`: Agent run created and queued
    - `application/json`:
      - type: `object (35 properties)`
      - `agent_name`: `['string', 'null']`
        - description: Name of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `agent_slug`: `['string', 'null']`
        - description: Slug of the agent that created this run, if available.
        - type: `['string', 'null']`
      - `ai_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_output`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_provider`: `['string', 'null']`
        - description: AI provider slug that executed this run (e.g. `claude_cli`, `codex_cli`, opencode).
        - type: `['string', 'null']`
      - `ai_reasoning`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_session_id`: `['string', 'null']`
        - description: Claude CLI session UUID for resuming conversations via `--resume`.
        - type: `['string', 'null']`
      - `analysis`: `['string', 'null']`
        - description: Report / analysis text produced by the agent (used for report/notification deliverables).
        - type: `['string', 'null']`
      - `branch_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_sha`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `ephemeral_definition`: `['string', 'null']`
        - description: The definition an ephemeral run executed, as `.md` text with every
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `estimated_cost_minor` *required*: `integer`
        - type: `integer`
      - `files_changed` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `phase`: `['string', 'null']`
        - description: Autofixer phase: "analyzing", "analyzed", "fixing", `"fix_ready"`, `"no_fix"`,
        - type: `['string', 'null']`
      - `pr_number`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `pr_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preview_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `prompt_text`: `['string', 'null']`
        - description: Final assembled prompt the AI CLI actually saw (trigger context block +
        - type: `['string', 'null']`
      - `provenance`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `run_config`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `source` *required*: `string`
        - description: `committed` (the run's config lives in `project_agents`) or
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tokens_input` *required*: `integer`
        - type: `integer`
      - `tokens_output` *required*: `integer`
        - type: `integer`
      - `trigger_source_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `trigger_source_ref`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_source_type`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `user_context`: `['string', 'null']`
        - description: User-provided context for this run (e.g. webhook payload, manual instructions).
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `402`: Daily budget exceeded
  - `403`: Insufficient permissions
  - `404`: Project or agent not found in this workspace
  - `422`: AI CLI not installed
  - `429`: Cooldown active
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/aggregated-buckets`

- operationId: `get_aggregated_buckets`
- summary: Time-bucketed aggregates for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `aggregation_level` (query): `string`
  - `bucket_size` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved aggregated buckets
    - `application/json`:
      - type: `object (4 properties)`
      - `aggregation_level` *required*: `string`
        - type: `string`
      - `bucket_size` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations`

- operationId: `find_conversation`
- summary: Find the existing chat for a context (`null` when none yet).
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `context_type` (query) *required*: `string`
  - `context_id` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The conversation, or null
    - `application/json`:
      - type: `object (7 properties) | null`
  - `400`: Over-length lookup key
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations`

- operationId: `create_conversation`
- summary: Get-or-create the chat for a context (seeds it on first open).
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `context_id` *required*: `string`
      - description: The entity id (ints stringified).
      - type: `string`
    - `context_type` *required*: `string`
      - description: e.g. `"deployment"`.
      - type: `string`
- responses:
  - `200`: The conversation
    - `application/json`:
      - type: `object (7 properties)`
      - `context_id` *required*: `string`
        - type: `string`
      - `context_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `last_activity_at` *required*: `string`
        - type: `string`
      - `public_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Over-length context key
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project not found in this workspace
  - `409`: No AI provider configured

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/list`

- operationId: `list_conversations`
- summary: List a project's active conversations, most-recently-active first.
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Active conversations
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/{public_id}`

- operationId: `get_conversation`
- summary: Full conversation history (excluding the internal system seed).
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Conversation with messages
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project or conversation not found in this workspace

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/{public_id}`

- operationId: `rename_conversation`
- summary: Rename a conversation (set its human-facing title).
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `public_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `title` *required*: `string`
      - description: New human-facing title. Trimmed; must be non-empty after trimming.
      - type: `string`
- responses:
  - `200`: Renamed conversation
    - `application/json`:
      - type: `object (7 properties)`
      - `context_id` *required*: `string`
        - type: `string`
      - `context_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `last_activity_at` *required*: `string`
        - type: `string`
      - `public_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Empty or over-length title
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project or conversation not found in this workspace

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/{public_id}`

- operationId: `delete_ai_conversation`
- summary: Delete a conversation and its messages for good (G3f).
- description: Its creator may, whatever their role now (it is their own data), and so
may an owner or admin of the organization in a browser session. Anyone
else, and an unknown id, gets the same 404. Not gated on the project's
AI-chat toggle: deleting what is stored must not depend on a feature
switch.
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Deleted with its messages
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or a deployment token
  - `404`: Project or conversation not found, or not the caller's to delete

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/{public_id}/archive`

- operationId: `archive_conversation`
- summary: Archive (soft-delete) a conversation.
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Archived
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project or conversation not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/conversations/{public_id}/runs`

- operationId: `start_chat_run`
- summary: Run the conversation's assistant for the input's last user message and
stream the turn as AG-UI (TS5.5; not durable, D-TS10).
- tags: `AI Chat v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `public_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object`
- responses:
  - `200`: AG-UI Server-Sent Events, not durable
    - `text/event-stream`:
      - type: `any`
  - `400`: threadId is not the conversation, or no user message text (urn:conusai:ai-chat:input-invalid)
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or AI chat disabled for the project
  - `404`: Project or conversation not found in this workspace
  - `409`: No AI provider configured

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/tool-actions`

- operationId: `list_ai_tool_actions`
- tags: `AI Tool Actions`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (18 properties)>`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/tool-actions/{action_public_id}`

- operationId: `get_ai_tool_action`
- tags: `AI Tool Actions`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `action_public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (18 properties)`
      - `arguments`: `any`
        - type: `any`
      - `confirmed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `confirmed_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `content_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `credential_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `executed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `public_id` *required*: `string`
        - type: `string`
      - `redacted` *required*: `boolean`
        - description: Retention replaced the proposal and outcome (D9).
        - type: `boolean`
      - `result`: `any`
        - type: `any`
      - `risk_class`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tool_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `tool_name`: `['string', 'null']`
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/tool-actions/{action_public_id}/confirm`

- operationId: `confirm_ai_tool_action`
- tags: `AI Tool Actions`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `action_public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (18 properties)`
      - `arguments`: `any`
        - type: `any`
      - `confirmed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `confirmed_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `content_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `credential_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `executed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `public_id` *required*: `string`
        - type: `string`
      - `redacted` *required*: `boolean`
        - description: Retention replaced the proposal and outcome (D9).
        - type: `boolean`
      - `result`: `any`
        - type: `any`
      - `risk_class`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tool_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `tool_name`: `['string', 'null']`
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/ai/tool-actions/{action_public_id}/reject`

- operationId: `reject_ai_tool_action`
- tags: `AI Tool Actions`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `action_public_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (18 properties)`
      - `arguments`: `any`
        - type: `any`
      - `confirmed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `confirmed_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `content_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `credential_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `executed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `expires_at` *required*: `string`
        - type: `string`
      - `public_id` *required*: `string`
        - type: `string`
      - `redacted` *required*: `boolean`
        - description: Retention replaced the proposal and outcome (D9).
        - type: `boolean`
      - `result`: `any`
        - type: `any`
      - `risk_class`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tool_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `tool_name`: `['string', 'null']`
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/alarms`

- operationId: `listProjectAlarms`
- summary: List a project's alarms, filtered and paginated.
- tags: `Alarms v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `alarm_type` (query): `['string', 'null']`
  - `status` (query): `['string', 'null']`
  - `severity` (query): `['string', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `deployment_id` (query): `['integer', 'null']`
  - `service_id` (query): `['integer', 'null']`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Paginated list of alarms
    - `application/json`:
      - type: `object (4 properties)`
      - `items` *required*: `array<object (18 properties)>`
        - type: `array<object (18 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `400`: Invalid filter value
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/alarms/summary`

- operationId: `getProjectAlarmsSummary`
- summary: Alarm counts by status/severity/type for a project.
- tags: `Alarms v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Alarm summary counts
    - `application/json`:
      - type: `object (6 properties)`
      - `acknowledged` *required*: `integer`
        - type: `integer`
      - `by_type` *required*: `object`
        - type: `object`
      - `critical` *required*: `integer`
        - type: `integer`
      - `firing` *required*: `integer`
        - type: `integer`
      - `total_active` *required*: `integer`
        - type: `integer`
      - `warning` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/alarms/{alarm_id}/acknowledge`

- operationId: `acknowledgeAlarm`
- summary: Acknowledge a firing alarm (marks it seen, not resolved).
- description: The audit row is written by the legacy body this delegates to, so the write
is recorded exactly once and with the same `ALARM_ACKNOWLEDGED` operation
type as the legacy route.
- tags: `Alarms v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `alarm_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Alarm acknowledged
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or alarm not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/alarms/{alarm_id}/resolve`

- operationId: `resolveAlarm`
- summary: Resolve an alarm.
- description: The audit row is written by the legacy body this delegates to.
- tags: `Alarms v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `alarm_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Alarm resolved
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or alarm not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/active-visitors`

- operationId: `get_analytics_active_visitors`
- summary: Active-visitor count for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `window_minutes` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Active visitor count
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/event-detail`

- operationId: `get_event_detail`
- summary: Detail for one event name in one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `event_name` (query) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `bucket_interval` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Event detail
    - `application/json`:
      - type: `object (9 properties)`
      - `activity_over_time` *required*: `array<object (3 properties)>`
        - description: Time series data for event activity graph
        - type: `array<object (3 properties)>`
      - `browsers` *required*: `array<object (3 properties)>`
        - description: Browser distribution of visitors who triggered this event
        - type: `array<object (3 properties)>`
      - `bucket_interval` *required*: `string`
        - description: Bucket interval used for time series ('hour', 'day', etc.)
        - type: `string`
      - `countries` *required*: `array<object (4 properties)>`
        - description: Geographic distribution of visitors who triggered this event
        - type: `array<object (4 properties)>`
      - `event_name` *required*: `string`
        - description: The event name being analyzed
        - type: `string`
      - `referrers` *required*: `array<object (3 properties)>`
        - description: Top referrer hostnames for visitors who triggered this event
        - type: `array<object (3 properties)>`
      - `total_count` *required*: `integer`
        - description: Total number of times this event was triggered in the date range
        - type: `integer`
      - `unique_sessions` *required*: `integer`
        - description: Number of unique sessions where this event occurred
        - type: `integer`
      - `unique_visitors` *required*: `integer`
        - description: Number of unique visitors who triggered this event
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/event-visitors`

- operationId: `get_event_visitors`
- summary: Visitors who fired one event in one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `event_name` (query) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitors for the event
    - `application/json`:
      - type: `object (5 properties)`
      - `event_name` *required*: `string`
        - description: The event name
        - type: `string`
      - `page` *required*: `integer`
        - description: Current page number
        - type: `integer`
      - `per_page` *required*: `integer`
        - description: Items per page
        - type: `integer`
      - `total_count` *required*: `integer`
        - description: Total number of unique visitors who triggered this event
        - type: `integer`
      - `visitors` *required*: `array<object (11 properties)>`
        - description: Individual visitors who triggered this event
        - type: `array<object (11 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/events`

- operationId: `get_analytics_events_count`
- summary: Count events in one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `limit` (query): `integer`
  - `custom_events_only` (query): `boolean`
  - `breakdown` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Event counts
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/friction/tick`

- operationId: `post_friction_tick`
- summary: Recompute one project's friction reports for the previous UTC day
(observe-sdk P6.1). Backs the CLI's `conusai analytics friction-tick`.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `now` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Friction reports recomputed for the window
    - `application/json`:
      - type: `object (4 properties)`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `reports_written` *required*: `integer`
        - type: `integer`
      - `window_end` *required*: `string`
        - type: `string`
      - `window_start` *required*: `string`
        - type: `string`
  - `400`: Invalid now parameter
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/has-events`

- operationId: `check_analytics_has_events`
- summary: Whether one project has recorded any analytics events.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Whether events exist
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/live-visitors`

- operationId: `get_live_visitors_list`
- summary: The live-visitor list for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `window_minutes` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Live visitors
    - `application/json`:
      - type: `object (3 properties)`
      - `total_count` *required*: `integer`
        - type: `integer`
      - `visitors` *required*: `array<object (24 properties)>`
        - type: `array<object (24 properties)>`
      - `window_minutes` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-flow`

- operationId: `get_page_flow`
- summary: Page-to-page flow for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `limit` (query): `integer`
  - `transitions_limit` (query): `integer`
  - `min_views_for_dropoff` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Page flow
    - `application/json`:
      - type: `object (6 properties)`
      - `drop_off_points` *required*: `array<object (4 properties)>`
        - description: Top drop-off points (highest exit rates with meaningful traffic)
        - type: `array<object (4 properties)>`
      - `top_entry_pages` *required*: `array<object (9 properties)>`
        - description: Top entry pages (where visitors land), sorted by `entry_count` DESC
        - type: `array<object (9 properties)>`
      - `top_exit_pages` *required*: `array<object (9 properties)>`
        - description: Top exit pages (where visitors leave), sorted by `exit_count` DESC
        - type: `array<object (9 properties)>`
      - `total_pages` *required*: `integer`
        - description: Total unique pages seen in the period
        - type: `integer`
      - `total_sessions` *required*: `integer`
        - description: Total sessions in the period
        - type: `integer`
      - `transitions` *required*: `array<object (4 properties)>`
        - description: Page-to-page transitions (most common navigation paths)
        - type: `array<object (4 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-hourly-sessions`

- operationId: `get_page_hourly_sessions`
- summary: Hourly session counts per page for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page_path` (query) *required*: `string`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `bucket_interval` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Hourly sessions
    - `application/json`:
      - type: `object (4 properties)`
      - `hourly_data` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `hours` *required*: `integer`
        - type: `integer`
      - `page_path` *required*: `string`
        - type: `string`
      - `total_sessions` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-path-detail`

- operationId: `get_page_path_detail`
- summary: Detail for one page path.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page_path` (query) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `bucket_interval` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Page path detail
    - `application/json`:
      - type: `object (11 properties)`
      - `activity_over_time` *required*: `array<object (4 properties)>`
        - description: Time series data for activity graph
        - type: `array<object (4 properties)>`
      - `avg_time_on_page` *required*: `number`
        - description: Average time on page in seconds
        - type: `number`
      - `bounce_rate` *required*: `number`
        - description: Bounce rate percentage (0-100)
        - type: `number`
      - `bucket_interval` *required*: `string`
        - description: Bucket interval used for time series ('hour', 'day', etc.)
        - type: `string`
      - `countries` *required*: `array<object (5 properties)>`
        - description: Geographic distribution of visitors
        - type: `array<object (5 properties)>`
      - `entry_rate` *required*: `number`
        - description: Entry rate - percentage of sessions that started on this page
        - type: `number`
      - `exit_rate` *required*: `number`
        - description: Exit rate - percentage of sessions that ended on this page
        - type: `number`
      - `page_path` *required*: `string`
        - description: The page path being analyzed
        - type: `string`
      - `referrers` *required*: `array<object (3 properties)>`
        - description: Top referrers to this page
        - type: `array<object (3 properties)>`
      - `total_page_views` *required*: `integer`
        - description: Total page views in the date range
        - type: `integer`
      - `unique_visitors` *required*: `integer`
        - description: Total unique visitors to this page in the date range
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-path-visitors`

- operationId: `get_page_path_visitors`
- summary: Visitors who reached one page path.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page_path` (query) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitors for the page path
    - `application/json`:
      - type: `object (5 properties)`
      - `page` *required*: `integer`
        - description: Current page number
        - type: `integer`
      - `page_path` *required*: `string`
        - description: The page path
        - type: `string`
      - `per_page` *required*: `integer`
        - description: Items per page
        - type: `integer`
      - `sessions` *required*: `array<object (16 properties)>`
        - description: Individual visitor sessions
        - type: `array<object (16 properties)>`
      - `total_count` *required*: `integer`
        - description: Total number of visitor sessions matching the query
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-paths`

- operationId: `get_page_paths`
- summary: Page paths recorded for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `start_date` (query): `string`
  - `end_date` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Page paths
    - `application/json`:
      - type: `object (2 properties)`
      - `page_paths` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/page-paths-sparklines`

- operationId: `get_page_paths_sparklines`
- summary: Sparkline series per page path for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
  - `page_paths` (query) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Sparkline series
    - `application/json`:
      - type: `object (1 properties)`
      - `sparklines` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/recent-activity`

- operationId: `get_recent_activity`
- summary: Recent activity feed for one project.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `since_id` (query): `integer`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Recent activity
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - description: Total events returned
        - type: `integer`
      - `events` *required*: `array<object (17 properties)>`
        - description: Recent events, newest first
        - type: `array<object (17 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/sessions/{session_id}`

- operationId: `get_session_details`
- summary: Detail for one session.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_id` (path) *required*: `integer`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Session detail
    - `application/json`:
      - type: `object (11 properties)`
      - `duration_seconds` *required*: `integer`
        - type: `integer`
      - `ended_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `entry_path`: `['string', 'null']`
        - type: `['string', 'null']`
      - `exit_path`: `['string', 'null']`
        - type: `['string', 'null']`
      - `is_bounced` *required*: `boolean`
        - type: `boolean`
      - `is_engaged` *required*: `boolean`
        - type: `boolean`
      - `page_views` *required*: `integer`
        - type: `integer`
      - `referrer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `session_id` *required*: `integer`
        - type: `integer`
      - `started_at` *required*: `string`
        - type: `string`
      - `visitor_id` *required*: `string`
        - type: `string`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/sessions/{session_id}/events`

- operationId: `get_analytics_session_events`
- summary: Events recorded in one session.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_id` (path) *required*: `integer`
  - `start_date` (query): `string`
  - `end_date` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `environment_id` (query): `integer`
  - `sort_order` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Session events
    - `application/json`:
      - type: `object (5 properties)`
      - `events` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `limit` *required*: `integer`
        - type: `integer`
      - `offset` *required*: `integer`
        - type: `integer`
      - `session_id` *required*: `integer`
        - type: `integer`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/sessions/{session_id}/logs`

- operationId: `get_session_logs`
- summary: Console logs captured during one session.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_id` (path) *required*: `integer`
  - `start_date` (query): `string`
  - `end_date` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `environment_id` (query): `integer`
  - `visitor_id` (query): `integer`
  - `sort_order` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Session logs
    - `application/json`:
      - type: `object (5 properties)`
      - `limit` *required*: `integer`
        - type: `integer`
      - `logs` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `offset` *required*: `integer`
        - type: `integer`
      - `session_id` *required*: `integer`
        - type: `integer`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitor-facets`

- operationId: `get_visitor_facets`
- summary: Facet counts across one project's visitors.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `include_crawlers` (query): `boolean`
  - `has_activity_only` (query): `boolean`
  - `per_facet_limit` (query): `integer`
  - `filter_country` (query): `string`
  - `filter_region` (query): `string`
  - `filter_city` (query): `string`
  - `filter_channel` (query): `string`
  - `filter_referrer` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Visitor facets
    - `application/json`:
      - type: `object (5 properties)`
      - `channel` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `city` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `country` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `referrer` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `region` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors`

- operationId: `get_visitors`
- summary: List one project's visitors.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `include_crawlers` (query): `boolean`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `has_activity_only` (query): `boolean`
  - `filter_country` (query): `string`
  - `filter_region` (query): `string`
  - `filter_city` (query): `string`
  - `filter_channel` (query): `string`
  - `filter_referrer` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Visitors in the project
    - `application/json`:
      - type: `object (3 properties)`
      - `filtered_count` *required*: `integer`
        - type: `integer`
      - `total_count` *required*: `integer`
        - type: `integer`
      - `visitors` *required*: `array<object (24 properties)>`
        - type: `array<object (24 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/guid/{visitor_id}`

- operationId: `get_visitor_by_guid`
- summary: A visitor addressed by GUID.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Visitor record
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/id/{id}`

- operationId: `get_visitor_by_id`
- summary: A visitor addressed by row id.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor record
    - `application/json`:
      - type: `object (22 properties)`
      - `city`: `['string', 'null']`
        - type: `['string', 'null']`
      - `country`: `['string', 'null']`
        - type: `['string', 'null']`
      - `country_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `crawler_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `custom_data`: `any`
        - type: `any`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `first_channel`: `['string', 'null']`
        - description: Marketing channel from the first visit (e.g. "Organic Search", "Direct")
        - type: `['string', 'null']`
      - `first_referrer`: `['string', 'null']`
        - description: Full referrer URL from the visitor's first session
        - type: `['string', 'null']`
      - `first_referrer_hostname`: `['string', 'null']`
        - description: Hostname extracted from `first_referrer`
        - type: `['string', 'null']`
      - `first_seen` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_address`: `['string', 'null']`
        - type: `['string', 'null']`
      - `is_crawler` *required*: `boolean`
        - type: `boolean`
      - `is_eu`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `last_seen` *required*: `string`
        - type: `string`
      - `latitude`: `['number', 'null']`
        - type: `['number', 'null']`
      - `longitude`: `['number', 'null']`
        - type: `['number', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `region`: `['string', 'null']`
        - type: `['string', 'null']`
      - `timezone`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_agent`: `['string', 'null']`
        - type: `['string', 'null']`
      - `visitor_id` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}`

- operationId: `get_visitor_details`
- summary: Full detail for one visitor.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor detail
    - `application/json`:
      - type: `object (23 properties)`
      - `city`: `['string', 'null']`
        - type: `['string', 'null']`
      - `country`: `['string', 'null']`
        - type: `['string', 'null']`
      - `country_code`: `['string', 'null']`
        - type: `['string', 'null']`
      - `crawler_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `custom_data`: `any`
        - type: `any`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `first_channel`: `['string', 'null']`
        - description: Marketing channel from the first visit (e.g. "Organic Search", "Direct")
        - type: `['string', 'null']`
      - `first_referrer`: `['string', 'null']`
        - description: Full referrer URL from the visitor's first session
        - type: `['string', 'null']`
      - `first_referrer_hostname`: `['string', 'null']`
        - description: Hostname extracted from `first_referrer`
        - type: `['string', 'null']`
      - `first_seen` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `ip_address`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ip_address_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `is_crawler` *required*: `boolean`
        - type: `boolean`
      - `is_eu`: `['boolean', 'null']`
        - type: `['boolean', 'null']`
      - `last_seen` *required*: `string`
        - type: `string`
      - `latitude`: `['number', 'null']`
        - type: `['number', 'null']`
      - `longitude`: `['number', 'null']`
        - type: `['number', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `region`: `['string', 'null']`
        - type: `['string', 'null']`
      - `timezone`: `['string', 'null']`
        - type: `['string', 'null']`
      - `user_agent`: `['string', 'null']`
        - type: `['string', 'null']`
      - `visitor_id` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}/enrich`

- operationId: `enrich_visitor`
- summary: Attach identifying data to one visitor.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `custom_data` *required*: `object`
      - type: `object`
- responses:
  - `200`: Visitor enriched
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `visitor_id` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}/info`

- operationId: `get_visitor_info`
- summary: The stored record for one visitor.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor record
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}/journey`

- operationId: `get_visitor_journey`
- summary: One visitor's ordered page journey.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `limit_sessions` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor journey
    - `application/json`:
      - type: `object (4 properties)`
      - `sessions` *required*: `array<object (17 properties)>`
        - description: Sessions with their events, ordered newest first
        - type: `array<object (17 properties)>`
      - `total_events` *required*: `integer`
        - description: Total number of events across all sessions
        - type: `integer`
      - `total_sessions` *required*: `integer`
        - description: Total number of sessions
        - type: `integer`
      - `visitor_id` *required*: `integer`
        - description: Visitor internal ID
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}/sessions`

- operationId: `get_analytics_visitor_sessions`
- summary: Sessions belonging to one visitor.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `environment_id` (query): `integer`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor sessions
    - `application/json`:
      - type: `object (3 properties)`
      - `sessions` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
      - `total_sessions` *required*: `integer`
        - type: `integer`
      - `visitor_id` *required*: `string`
        - type: `string`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/analytics/visitors/{visitor_id}/stats`

- operationId: `get_visitor_stats`
- summary: Aggregate statistics for one visitor.
- tags: `Analytics v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor statistics
    - `application/json`:
      - type: `object (13 properties)`
      - `average_session_duration` *required*: `number`
        - type: `number`
      - `bounce_rate` *required*: `number`
        - type: `number`
      - `devices_used` *required*: `array<string>`
        - type: `array<string>`
      - `engagement_rate` *required*: `number`
        - type: `number`
      - `first_seen` *required*: `string`
        - type: `string`
      - `last_seen` *required*: `string`
        - type: `string`
      - `locations` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `top_pages` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `top_referrers` *required*: `array<string>`
        - type: `array<string>`
      - `total_events` *required*: `integer`
        - type: `integer`
      - `total_page_views` *required*: `integer`
        - type: `integer`
      - `total_sessions` *required*: `integer`
        - type: `integer`
      - `visitor_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/asset-cache`

- operationId: `purge_asset_cache`
- summary: Purge every cached static asset for a project.
- description: The legacy twin of this operation carries a `#[utoipa::path]` attribute that
appears in no `#[openapi(paths(...))]` list, so it is absent from the served
document. This one is registered.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Asset cache purged
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/audit/events`

- operationId: `ingest_scoped`
- summary: `POST {PROJECT_SCOPE_PREFIX}/audit/events`: the authenticated twin for
API keys, CI and agents (D5).
- tags: `Audit ingest`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `events` *required*: `array<object (16 properties)>`
      - description: The batch. At most 500 events; validation is all-or-nothing.
      - type: `array<object (16 properties)>`
    - `v`: `['integer', 'null']`
      - description: Contract version. Optional today, must be `1` when present; required
      - type: `['integer', 'null']`
- responses:
  - `202`: Accepted
    - `application/json`:
      - type: `object (3 properties)`
      - `accepted` *required*: `integer`
        - description: Events newly written.
        - type: `integer`
      - `duplicates` *required*: `integer`
        - description: Events skipped because their `event_id` was already stored.
        - type: `integer`
      - `redacted` *required*: `array<string>`
        - description: Paths of PII values replaced before hashing, e.g.
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Not Found
  - `413`: Payload Too Large
  - `422`: Unprocessable Entity
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Too Many Requests

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/audit/retention`

- operationId: `get_project_retention_v2`
- summary: Read the path project's retention tiers (the project twin of the org
route). The project is fixed by the path.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The project's retention tiers (or the effective defaults)
    - `application/json`:
      - type: `object (7 properties)`
      - `access_enabled` *required*: `boolean`
        - description: Whether access-tier pruning is on for this scope (opt-in)
        - type: `boolean`
      - `access_retain_days` *required*: `integer`
        - description: Days access-class rows are kept; never below 1
        - type: `integer`
      - `admin_retain_days` *required*: `integer`
        - description: Days admin-class rows are kept; never below 365 (NIST AU-11 floor)
        - type: `integer`
      - `configured` *required*: `boolean`
        - description: `false` when no row is stored and the values are the defaults
        - type: `boolean`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - description: `null` on the org-wide row; the path's project on the project route
        - type: `['integer', 'null']`
      - `updated_at`: `['string', 'null']`
        - description: RFC 3339 UTC of the last write; `null` when `configured` is false
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Organization, workspace or project not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/audit/retention`

- operationId: `put_project_retention_v2`
- summary: Write the path project's retention tiers. The path fixes the project —
the body has no `project_id` field to override it with.
- tags: `Audit v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `access_enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `access_retain_days` *required*: `integer`
      - type: `integer`
    - `admin_retain_days` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: The stored project tiers
    - `application/json`:
      - type: `object (7 properties)`
      - `access_enabled` *required*: `boolean`
        - description: Whether access-tier pruning is on for this scope (opt-in)
        - type: `boolean`
      - `access_retain_days` *required*: `integer`
        - description: Days access-class rows are kept; never below 1
        - type: `integer`
      - `admin_retain_days` *required*: `integer`
        - description: Days admin-class rows are kept; never below 365 (NIST AU-11 floor)
        - type: `integer`
      - `configured` *required*: `boolean`
        - description: `false` when no row is stored and the values are the defaults
        - type: `boolean`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `project_id`: `['integer', 'null']`
        - description: `null` on the org-wide row; the path's project on the project route
        - type: `['integer', 'null']`
      - `updated_at`: `['string', 'null']`
        - description: RFC 3339 UTC of the last write; `null` when `configured` is false
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions (requires audit:write)
  - `404`: Organization, workspace or project not found
  - `422`: Below the D13 floors
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/analyze`

- operationId: `start_analysis`
- summary: Start an autofixer analysis run for one error group.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `branch`: `['string', 'null']`
      - description: Branch to clone instead of the project's main branch.
      - type: `['string', 'null']`
    - `error_group_id` *required*: `integer`
      - type: `integer`
    - `max_turns`: `['integer', 'null']`
      - description: Per-run turn cap applied to every phase (1–200). Only enforced for
      - type: `['integer', 'null']`
    - `model`: `['string', 'null']`
      - description: Model id for the chosen provider. `None` uses the provider's saved
      - type: `['string', 'null']`
    - `provider`: `['string', 'null']`
      - description: AI provider id (`"claude_cli"`, `"codex_cli"`, "opencode"). `None` uses
      - type: `['string', 'null']`
    - `user_context`: `['string', 'null']`
      - description: Free-text notes for the model (extra context about the error, retry
      - type: `['string', 'null']`
- responses:
  - `202`: Analysis started; returns run_id for streaming
    - `application/json`:
      - type: `object (21 properties)`
      - `ai_model`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_output`: `['string', 'null']`
        - type: `['string', 'null']`
      - `ai_provider`: `['string', 'null']`
        - description: AI provider slug this run executes with (e.g. `claude_cli`, `codex_cli`).
        - type: `['string', 'null']`
      - `analysis`: `['string', 'null']`
        - type: `['string', 'null']`
      - `branch_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `files_changed` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `phase`: `['string', 'null']`
        - type: `['string', 'null']`
      - `pr_number`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `pr_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `run_config`: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tokens_input` *required*: `integer`
        - type: `integer`
      - `tokens_output` *required*: `integer`
        - type: `integer`
      - `trigger_source_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `user_context`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/runs/{run_id}`

- operationId: `get_autofixer_run`
- summary: Read one autofixer run together with its logs.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Run with logs
    - `application/json`:
      - type: `object (2 properties)`
      - `logs` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `run` *required*: `object (21 properties)`
        - type: `object (21 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/runs/{run_id}/add-context`

- operationId: `add_autofixer_context`
- summary: Append user context to an in-flight autofixer run.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `message` *required*: `string`
      - type: `string`
- responses:
  - `200`: Context appended
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/runs/{run_id}/create-pr`

- operationId: `create_autofixer_pr`
- summary: Open a pull request from a completed autofixer run.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `201`: PR created
    - `application/json`:
      - type: `object (4 properties)`
      - `branch_name` *required*: `string`
        - type: `string`
      - `pr_number` *required*: `integer`
        - type: `integer`
      - `pr_url` *required*: `string`
        - type: `string`
      - `run` *required*: `object (21 properties)`
        - type: `object (21 properties)`
  - `400`: Run not in fix_ready phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/runs/{run_id}/fix`

- operationId: `start_autofixer_fix`
- summary: Start fix generation for an analyzed autofixer run.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Fix generation started
  - `400`: Run not in analyzed phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/autofixer/runs/{run_id}/re-analyze`

- operationId: `re_analyze_autofixer`
- summary: Continue an analyzed autofixer run with reviewer feedback.
- tags: `Autofixer v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Conversation continued with feedback
  - `400`: Run not in analyzed phase
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or run not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/automatic-deploy`

- operationId: `update_automatic_deploy`
- summary: Turn automatic deployment on or off for a project.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `automatic_deploy` *required*: `boolean`
      - type: `boolean`
- responses:
  - `200`: Automatic deployment setting updated
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/config/validate`

- operationId: `validate_project_config`
- summary: Validate a project's `conusai.json` and compose file.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `compose`: `['string', 'null']`
      - description: The contents of the compose file `conusai.json` names in
      - type: `['string', 'null']`
    - `conusai_json` *required*: `string`
      - description: The contents of `conusai.json`.
      - type: `string`
- responses:
  - `200`: The validation result; `valid` is false with the problems when the files would not deploy
    - `application/json`:
      - type: `object (2 properties)`
      - `problems` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `valid` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains`

- operationId: `list_custom_domains_for_project`
- summary: List a project's custom domains.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Custom domains for the project
    - `application/json`:
      - type: `object (2 properties)`
      - `domains` *required*: `array<object (18 properties)>`
        - type: `array<object (18 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains`

- operationId: `create_custom_domain`
- summary: Attach a custom domain to a project.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `branch`: `['string', 'null']`
      - type: `['string', 'null']`
    - `domain` *required*: `string`
      - type: `string`
    - `environment_id` *required*: `integer`
      - type: `integer`
    - `redirect_to`: `['string', 'null']`
      - type: `['string', 'null']`
    - `service_name`: `['string', 'null']`
      - description: Docker Compose service name this domain routes to (only for docker-compose projects)
      - type: `['string', 'null']`
    - `status_code`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `201`: Custom domain created
    - `application/json`:
      - type: `object (18 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redirect_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Docker Compose service name this domain routes to
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_record` *required*: `object (2 properties)`
        - description: A DNS TXT record the tenant publishes to verify a custom domain.
        - type: `object (2 properties)`
      - `verified` *required*: `boolean`
        - description: Whether the domain's verification TXT record has been found. An
        - type: `boolean`
      - `verified_at`: `['integer', 'null']`
        - description: When the verification TXT record was last found (milliseconds).
        - type: `['integer', 'null']`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Domain already exists
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains/{domain_id}`

- operationId: `get_custom_domain`
- summary: Read one of a project's custom domains.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The custom domain
    - `application/json`:
      - type: `object (18 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redirect_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Docker Compose service name this domain routes to
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_record` *required*: `object (2 properties)`
        - description: A DNS TXT record the tenant publishes to verify a custom domain.
        - type: `object (2 properties)`
      - `verified` *required*: `boolean`
        - description: Whether the domain's verification TXT record has been found. An
        - type: `boolean`
      - `verified_at`: `['integer', 'null']`
        - description: When the verification TXT record was last found (milliseconds).
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or custom domain not found in this workspace
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains/{domain_id}`

- operationId: `update_custom_domain`
- summary: Update one of a project's custom domains.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `branch`: `['string', 'null']`
      - type: `['string', 'null']`
    - `domain`: `['string', 'null']`
      - type: `['string', 'null']`
    - `environment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `redirect_to`: `['string', 'null']`
      - type: `['string', 'null']`
    - `service_name`: `['string', 'null']`
      - description: Docker Compose service name this domain routes to (empty string clears it)
      - type: `['string', 'null']`
    - `status_code`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: The updated custom domain
    - `application/json`:
      - type: `object (18 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redirect_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Docker Compose service name this domain routes to
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_record` *required*: `object (2 properties)`
        - description: A DNS TXT record the tenant publishes to verify a custom domain.
        - type: `object (2 properties)`
      - `verified` *required*: `boolean`
        - description: Whether the domain's verification TXT record has been found. An
        - type: `boolean`
      - `verified_at`: `['integer', 'null']`
        - description: When the verification TXT record was last found (milliseconds).
        - type: `['integer', 'null']`
  - `400`: Invalid input
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or custom domain not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains/{domain_id}`

- operationId: `delete_custom_domain`
- summary: Detach a custom domain from a project.
- description: Removes the `project_custom_domains` row. The `domains` row holding the
issued certificate and its private key is not touched.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Custom domain deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or custom domain not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains/{domain_id}/link-certificate/{certificate_id}`

- operationId: `link_custom_domain_to_certificate`
- summary: Point a custom domain at an issued certificate.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
  - `certificate_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The linked custom domain
    - `application/json`:
      - type: `object (18 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redirect_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Docker Compose service name this domain routes to
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_record` *required*: `object (2 properties)`
        - description: A DNS TXT record the tenant publishes to verify a custom domain.
        - type: `object (2 properties)`
      - `verified` *required*: `boolean`
        - description: Whether the domain's verification TXT record has been found. An
        - type: `boolean`
      - `verified_at`: `['integer', 'null']`
        - description: When the verification TXT record was last found (milliseconds).
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, custom domain or certificate not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/custom-domains/{domain_id}/verify`

- operationId: `verify_custom_domain`
- summary: Check a custom domain's verification TXT record; routes it once found.
- description: A custom domain serves no traffic until verified (owner decision O6): the
caller publishes `verification_record.value` as a TXT record at
`verification_record.name`, then calls this.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The verified custom domain
    - `application/json`:
      - type: `object (18 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `domain_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment`: `object (3 properties) | null`
        - type: `object (3 properties) | null`
      - `expiration_time`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_renewed`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redirect_to`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Docker Compose service name this domain routes to
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `verification_record` *required*: `object (2 properties)`
        - description: A DNS TXT record the tenant publishes to verify a custom domain.
        - type: `object (2 properties)`
      - `verified` *required*: `boolean`
        - description: Whether the domain's verification TXT record has been found. An
        - type: `boolean`
      - `verified_at`: `['integer', 'null']`
        - description: When the verification TXT record was last found (milliseconds).
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or custom domain not found
  - `422`: The verification TXT record was not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-config`

- operationId: `update_project_deployment_config`
- summary: Update a project's deployment configuration (resources, replicas, security).
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `automaticDeploy`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `cpuLimit`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `cpuRequest`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `crossArchitectureBuilds`: `['boolean', 'null']`
      - description: Build one image per architecture the eligible nodes run. Off by
      - type: `['boolean', 'null']`
    - `exposedPort`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `memoryLimit`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `memoryRequest`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `performanceMetricsEnabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `replicas`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `security`: `object (7 properties) | null`
      - type: `object (7 properties) | null`
    - `sessionRecordingEnabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `tokenPermissions`: `['array', 'null']`
      - description: Runtime scope requests for image deployments; owner/admin approval remains separate.
      - type: `['array', 'null']`
- responses:
  - `200`: Deployment configuration updated
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid deployment configuration
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens`

- operationId: `list_deployment_tokens`
- summary: List a project's deployment tokens.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment tokens for the project
    - `application/json`:
      - type: `object (2 properties)`
      - `tokens` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens`

- operationId: `create_deployment_token`
- summary: Create a deployment token for a project.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `deployment_id`: `['integer', 'null']`
      - description: Optional deployment ID - if set, token is scoped to a specific deployment
      - type: `['integer', 'null']`
    - `environment_id`: `['integer', 'null']`
      - description: Optional environment ID - if not set, token applies to all environments
      - type: `['integer', 'null']`
    - `expires_at`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `permissions`: `['array', 'null']`
      - description: List of permissions (e.g., ["visitors:enrich", "emails:send"])
      - type: `['array', 'null']`
- responses:
  - `201`: Deployment token created
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `requires_redeploy` *required*: `boolean`
        - description: True when live containers are still holding the previous secret.
        - type: `boolean`
      - `token` *required*: `string`
        - description: The full token value - only returned on creation
        - type: `string`
      - `token_prefix` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Token with this name already exists
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens/{token_id}`

- operationId: `get_deployment_token`
- summary: Read one deployment token.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `token_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment token details
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `token_prefix` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or token not found in this workspace
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens/{token_id}`

- operationId: `update_deployment_token`
- summary: Update a deployment token.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `token_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `expires_at`: `['string', 'null']`
      - type: `['string', 'null']`
    - `is_active`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `permissions`: `['array', 'null']`
      - type: `['array', 'null']`
- responses:
  - `200`: Deployment token updated
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `last_used_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `name` *required*: `string`
        - type: `string`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `token_prefix` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or token not found in this workspace
  - `409`: Token with this name already exists
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens/{token_id}`

- operationId: `delete_deployment_token`
- summary: Delete a deployment token.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `token_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Deployment token deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or token not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens/{token_id}/rotate`

- operationId: `rotate_deployment_token`
- summary: Rotate a deployment token's secret.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `token_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment token rotated; the response carries the new plaintext token, shown only once
    - `application/json`:
      - type: `object (11 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `permissions`: `['array', 'null']`
        - type: `['array', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `requires_redeploy` *required*: `boolean`
        - description: True when live containers are still holding the previous secret.
        - type: `boolean`
      - `token` *required*: `string`
        - description: The full token value - only returned on creation
        - type: `string`
      - `token_prefix` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or token not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployment-tokens/{token_id}/scope-decision`

- operationId: `decide_deployment_token_scopes`
- summary: Approve or deny the runtime scopes requested for a deployment token.
- description: `approve` grants the scopes to the token. `deny` revokes them from the
token when held and withdraws them from the `deployment_config.token_permissions`
request of every environment the token serves, in the same transaction.
`scopes` absent or empty means every pending scope. Unknown scopes and `*`
are refused before any write. Organization owner or admin only. Every
decision that changes something is audited as
`DEPLOYMENT_TOKEN_SCOPE_DECISION`; if that audit write fails nothing is
changed.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `token_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `decision` *required*: `string`
      - description: What the owner or admin decided.
      - type: `string`
    - `scopes`: `['array', 'null']`
      - description: The scopes to decide. Absent or empty: every pending scope, i.e. every
      - type: `['array', 'null']`
- responses:
  - `200`: Decision applied (or nothing was pending); the body lists what changed
    - `application/json`:
      - type: `object (8 properties)`
      - `before_permissions` *required*: `array<string>`
        - description: The token's permissions before the decision.
        - type: `array<string>`
      - `decision` *required*: `string`
        - description: What the owner or admin decided.
        - type: `string`
      - `environment_ids` *required*: `array<integer>`
        - description: The environments whose request this token serves.
        - type: `array<integer>`
      - `granted` *required*: `array<string>`
        - description: Scopes added to the token (approve).
        - type: `array<string>`
      - `revoked` *required*: `array<string>`
        - description: Scopes removed from the token (deny).
        - type: `array<string>`
      - `scopes` *required*: `array<string>`
        - description: The scopes decided: the ones named, or every pending one.
        - type: `array<string>`
      - `token` *required*: `object (12 properties)`
        - type: `object (12 properties)`
      - `withdrawn` *required*: `array<object (2 properties)>`
        - description: Scopes withdrawn from environment requests (deny).
        - type: `array<object (2 properties)>`
  - `400`: Unknown or non-grantable scope (`*`); nothing changed
  - `401`: Unauthorized
  - `403`: Not an organization owner or admin
  - `404`: Project or token not found in this workspace
  - `500`: Internal server error, or the audit event could not be written; nothing changed

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments`

- operationId: `list_project_deployments`
- summary: List the project's deployments (the `kernel.deployment` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page; filter by
`environment_id` with `{"op":"eq","field":"environment_id","value":…}`.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (21 properties)>`
        - type: `array<object (21 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Bad Request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/_batch`

- operationId: `get_deployments_batch`
- summary: Read back deployments of this project by id.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible deployments among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (21 properties)>`
        - type: `array<object (21 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/activity-graph`

- operationId: `get_activity_graph`
- summary: Daily deployment counts for **this project**.
- description: # Why this one takes its project from the path rather than a query filter

The v1 endpoint projection projects `GET /deployments/activity-graph` to
this URI, and an earlier revision of this module reported the projection as
a defect and declined to implement it. The objection was that the legacy
handler takes a workspace scope and treats `project_id` as an *optional*
query filter, so with the filter absent it aggregates the whole
organization — and hanging a `{project_slug}` off a response that ignores it
asserts a tenancy the server does not enforce.

That objection is answered by *binding* the segment instead of decorating
with it. This handler passes `Some(scope.project().get())` as the filter, so
the project named in the URI is exactly the project the service groups by;
`DeploymentService::get_activity_graph` honours it, and the delegated body
additionally runs `project_scope_guard!` and `assert_project_in_scope`
against it. The segment is load-bearing, not ornamental.

**A `project_id` in the query string is deliberately ignored.** The path is
the authority under this grammar; honouring a query override would let a
caller address project A's URI and read project B's graph after the scope
check had already passed on A. The org-wide aggregate has no v1 spelling and
is not given one here — it is a different resource (an organization's
activity, not a project's) and belongs on an org-scoped route, which is a
surface decision rather than a mirroring one.

`activity-graph` is a literal segment at the same position as
`{deployment_id}`, which is the §4a shadowing shape. It is inert here:
`DeploymentPath::deployment_id` is an `i32`, so no deployment can ever be
addressed by a name that collides.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `days` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Daily deployment counts for the project
    - `application/json`:
      - type: `object (4 properties)`
      - `days` *required*: `array<object (3 properties)>`
        - description: Array of daily activity counts
        - type: `array<object (3 properties)>`
      - `end_date` *required*: `string`
        - description: Date range end (YYYY-MM-DD)
        - type: `string`
      - `start_date` *required*: `string`
        - description: Date range start (YYYY-MM-DD)
        - type: `string`
      - `total_count` *required*: `integer`
        - description: Total count of activities across all days
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/last`

- operationId: `get_last_deployment`
- summary: Get the most recent deployment for a project in the path-scoped v1 tree.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Most recent deployment
    - `application/json`:
      - type: `object (21 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cancelled_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_author`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_date`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `deployment_config`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `environment` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `finished_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `guides_publication`: `object (13 properties) | null`
        - type: `object (13 properties) | null`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_current` *required*: `boolean`
        - type: `boolean`
      - `metadata`: `object (26 properties) | null`
        - type: `object (26 properties) | null`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `screenshot_location`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
      - `url` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}`

- operationId: `get_deployment`
- summary: Get a single deployment in the path-scoped v1 tree.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment details
    - `application/json`:
      - type: `object (21 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cancelled_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_author`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_date`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `deployment_config`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `environment` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `finished_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `guides_publication`: `object (13 properties) | null`
        - type: `object (13 properties) | null`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_current` *required*: `boolean`
        - type: `boolean`
      - `metadata`: `object (26 properties) | null`
        - type: `object (26 properties) | null`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `screenshot_location`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
      - `url` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/cancel`

- operationId: `cancel_deployment`
- summary: Cancel an in-flight deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment cancelled
    - `application/json`:
      - type: `object (3 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `400`: Deployment already completed, failed or cancelled
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/container-logs`

- operationId: `list_deployment_container_logs`
- summary: List captured container logs for a deployment in the path-scoped v1 tree.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Captured container logs
    - `application/json`:
      - type: `object (1 properties)`
      - `logs` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/container-logs/{log_id}`

- operationId: `get_deployment_container_log_content`
- summary: Get the captured text of a single container log in the path-scoped v1 tree.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
  - `log_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Captured container log content
    - `application/json`:
      - type: `object (7 properties)`
      - `captured_at` *required*: `integer`
        - type: `integer`
      - `container_name` *required*: `string`
        - type: `string`
      - `content` *required*: `string`
        - description: The captured plain-text log content.
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `service_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `size_bytes` *required*: `integer`
        - type: `integer`
      - `truncated` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `404`: Project, deployment or log not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/jobs`

- operationId: `get_deployment_jobs`
- summary: List jobs for a deployment in the path-scoped v1 tree.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment jobs
    - `application/json`:
      - type: `object (2 properties)`
      - `jobs` *required*: `array<object (17 properties)>`
        - type: `array<object (17 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/jobs/{job_id}/logs`

- operationId: `get_deployment_job_logs`
- summary: Read a build/deploy job's captured log text.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
  - `job_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Job logs
    - `text/plain`:
      - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, deployment or job not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/jobs/{job_id}/logs/tail`

- operationId: `tail_deployment_job_logs`
- summary: Stream a build/deploy job's log lines over a `WebSocket`.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
  - `job_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `101`: WebSocket connection established for streaming job logs
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, deployment or job not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/operations`

- operationId: `get_deployment_operations`
- summary: List the operations recorded against an external deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Operations for the deployment
    - `application/json`:
      - type: `object (2 properties)`
      - `deployment_id` *required*: `string`
        - type: `string`
      - `operations` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/operations`

- operationId: `execute_deployment_operation`
- summary: Execute an operation against an external deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `operation` *required*: `string`
      - type: `string`
- responses:
  - `202`: Operation executed
    - `application/json`:
      - type: `object (5 properties)`
      - `data`: `any`
        - type: `any`
      - `executed_at` *required*: `string`
        - type: `string`
      - `message` *required*: `string`
        - type: `string`
      - `operation` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `400`: Invalid operation
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/operations/{operation_type}`

- operationId: `get_deployment_operation_status`
- summary: Read the latest status of one operation type on an external deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `string`
  - `operation_type` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Operation status
    - `application/json`:
      - type: `object (5 properties)`
      - `data`: `any`
        - type: `any`
      - `executed_at` *required*: `string`
        - type: `string`
      - `message` *required*: `string`
        - type: `string`
      - `operation` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `400`: Invalid operation type
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or operation not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/pause`

- operationId: `pause_deployment`
- summary: Pause a running deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment paused
    - `application/json`:
      - type: `object (3 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/promote`

- operationId: `promote_deployment`
- summary: Promote a deployment into another environment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `target_environment_id` *required*: `integer`
      - description: Target environment ID to promote the deployment to
      - type: `integer`
- responses:
  - `200`: Promotion initiated
    - `application/json`:
      - type: `object (21 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cancelled_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_author`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_date`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `deployment_config`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `environment` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `finished_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `guides_publication`: `object (13 properties) | null`
        - type: `object (13 properties) | null`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_current` *required*: `boolean`
        - type: `boolean`
      - `metadata`: `object (26 properties) | null`
        - type: `object (26 properties) | null`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `screenshot_location`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid deployment state for promotion
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, deployment or target environment not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/resume`

- operationId: `resume_deployment`
- summary: Resume a paused deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Deployment resumed
    - `application/json`:
      - type: `object (3 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/rollback`

- operationId: `rollback_to_deployment`
- summary: Roll a project's environment back to an earlier deployment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Rollback initiated
    - `application/json`:
      - type: `object (21 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cancelled_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_author`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_date`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `deployment_config`: `object (11 properties) | null`
        - type: `object (11 properties) | null`
      - `environment` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `finished_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `guides_publication`: `object (13 properties) | null`
        - type: `object (13 properties) | null`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_current` *required*: `boolean`
        - type: `boolean`
      - `metadata`: `object (26 properties) | null`
        - type: `object (26 properties) | null`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `screenshot_location`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
      - `url` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/teardown`

- operationId: `teardown_deployment`
- summary: Tear a single deployment down.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Deployment torn down
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or deployment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/deployments/{deployment_id}/vulnerability-scan`

- operationId: `get_scan_by_deployment`
- summary: The completed scan of one deployment, below the proven project.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `deployment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Scan for the specified deployment
    - `application/json`:
      - type: `object (20 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `critical_count` *required*: `integer`
        - type: `integer`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `high_count` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `low_count` *required*: `integer`
        - type: `integer`
      - `medium_count` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `scanner_type` *required*: `string`
        - type: `string`
      - `scanner_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `total_count` *required*: `integer`
        - type: `integer`
      - `unknown_count` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: No scan for this deployment in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/dsns`

- operationId: `list_dsns`
- summary: List the DSNs of one path-scoped project.
- tags: `dsn-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of DSNs
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/dsns`

- operationId: `create_dsn`
- summary: Create a DSN for one path-scoped project.
- tags: `dsn-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `deployment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `environment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: DSN created
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/dsns/get-or-create`

- operationId: `get_or_create_dsn`
- summary: Return the project's existing DSN, or create one if it has none.
- tags: `dsn-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
    - `deployment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `environment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: DSN returned or created
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/dsns/{dsn_id}/regenerate`

- operationId: `regenerate_dsn`
- summary: Rotate one DSN's key material, in place, for one path-scoped project.
- tags: `dsn-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `dsn_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `base_url`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: DSN regenerated
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: DSN not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/dsns/{dsn_id}/revoke`

- operationId: `revoke_dsn`
- summary: Revoke one DSN of one path-scoped project.
- tags: `dsn-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `dsn_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: DSN revoked
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: DSN not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars`

- operationId: `get_environment_variables`
- summary: List one project's environment variables.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment variables
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars`

- operationId: `create_environment_variable`
- summary: Create an environment variable in one project.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `available_at_build`: `['boolean', 'null']`
      - description: Whether a build receives this variable (K5.3). Omitted: a secret is
      - type: `['boolean', 'null']`
    - `environment_ids` *required*: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - description: Include this environment variable in preview environments (default: true)
      - type: `boolean`
    - `is_secret`: `boolean`
      - description: When true the variable is a secret: list, create and update never
      - type: `boolean`
    - `key` *required*: `string`
      - type: `string`
    - `value` *required*: `string`
      - type: `string`
- responses:
  - `201`: Variable created
    - `application/json`:
      - type: `object (9 properties)`
      - `available_at_build` *required*: `boolean`
        - description: Whether a build receives this variable; otherwise it reaches only the
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - description: Include this environment variable in preview environments
        - type: `boolean`
      - `is_secret` *required*: `boolean`
        - description: Whether the variable is a secret. Secrets always have `value: None` in
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `value`: `['string', 'null']`
        - description: Plaintext value for non-secret vars (or `"***"` mask for list responses).
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars/resolved`

- operationId: `get_resolved_environment_variables`
- summary: List one project's environment variables with inherited values resolved.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Resolved environment variables
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars/resolved/{key}/value`

- operationId: `get_resolved_environment_variable_value`
- summary: Reveal one resolved environment variable's value.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `key` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Resolved variable value
    - `application/json`:
      - type: `object (1 properties)`
      - `value` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Variable not found in this project
  - `500`: Internal server error
  - `503`: A secret reveal could not be audited; no value was released

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars/{key}/value`

- operationId: `get_environment_variable_value`
- summary: Reveal one environment variable's value.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `key` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Variable value
    - `application/json`:
      - type: `object (1 properties)`
      - `value` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Variable not found in this project
  - `500`: Internal server error
  - `503`: A secret reveal could not be audited; no value was released

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars/{var_id}`

- operationId: `update_environment_variable`
- summary: Update one environment variable.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `var_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `available_at_build`: `['boolean', 'null']`
      - description: Whether a build receives this variable (K5.3); omitted leaves it
      - type: `['boolean', 'null']`
    - `environment_ids` *required*: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - type: `boolean`
    - `is_secret`: `['boolean', 'null']`
      - description: Optional secret-flag transition.
      - type: `['boolean', 'null']`
    - `key` *required*: `string`
      - type: `string`
    - `value`: `['string', 'null']`
      - description: New plaintext value. `None` (omitted) keeps the existing ciphertext,
      - type: `['string', 'null']`
- responses:
  - `200`: Variable updated
    - `application/json`:
      - type: `object (9 properties)`
      - `available_at_build` *required*: `boolean`
        - description: Whether a build receives this variable; otherwise it reaches only the
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - description: Include this environment variable in preview environments
        - type: `boolean`
      - `is_secret` *required*: `boolean`
        - description: Whether the variable is a secret. Secrets always have `value: None` in
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
      - `value`: `['string', 'null']`
        - description: Plaintext value for non-secret vars (or `"***"` mask for list responses).
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Variable not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/env-vars/{var_id}`

- operationId: `delete_environment_variable`
- summary: Delete one environment variable.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `var_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Variable deleted
  - `401`: Unauthorized
  - `404`: Variable not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments`

- operationId: `list_environments`
- summary: List the environments of one project (the `kernel.environment` collection).
- description: Takes the collection query wire (`filter`, `order`, `limit`, `offset`,
`cursor`; final-wave contract C-05) and answers one page.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `order` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `cursor` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Environments in the project
    - `application/json`:
      - type: `object (3 properties)`
      - `boundary_complete` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (18 properties)>`
        - type: `array<object (18 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid collection query (`urn:conusai:collections:*`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments`

- operationId: `create_environment`
- summary: Create an environment in one project.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `branch` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `set_as_preview`: `boolean`
      - description: If true, set this environment as the preview environment for the project
      - type: `boolean`
- responses:
  - `201`: Environment created
    - `application/json`:
      - type: `object (18 properties)`
      - `attack_mode` *required*: `string`
        - description: An environment's CAPTCHA attack-mode setting (`environments.attack_mode`).
        - type: `string`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `current_deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_config`: `object (23 properties) | null`
        - type: `object (23 properties) | null`
      - `estimated_sleep_at`: `['integer', 'null']`
        - description: Estimated time (epoch millis) when the environment will go to sleep
        - type: `['integer', 'null']`
      - `https_redirect` *required*: `string`
        - description: An environment's HTTP→HTTPS redirect (`environments.https_redirect`).
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_preview` *required*: `boolean`
        - description: Indicates if this is a preview environment (auto-created per branch)
        - type: `boolean`
      - `last_activity_at`: `['integer', 'null']`
        - description: Last proxied request timestamp (epoch millis) for on-demand environments.
        - type: `['integer', 'null']`
      - `main_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `protected` *required*: `boolean`
        - description: When true, git pushes do NOT auto-deploy to this environment.
        - type: `boolean`
      - `sleeping` *required*: `boolean`
        - description: When true, the environment's containers are currently stopped due to
        - type: `boolean`
      - `slug` *required*: `string`
        - type: `string`
      - `subdomain` *required*: `string`
        - description: The host label stored for this environment (e.g.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/_batch`

- operationId: `get_environments_batch`
- summary: Read back environments of this project by id.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `ids` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The visible environments among the ids
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (18 properties)>`
        - type: `array<object (18 properties)>`
  - `400`: No ids or more than 100 (`urn:conusai:collections:too-many-ids`)
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}`

- operationId: `get_environment`
- summary: Read one environment of one project.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment details
    - `application/json`:
      - type: `object (18 properties)`
      - `attack_mode` *required*: `string`
        - description: An environment's CAPTCHA attack-mode setting (`environments.attack_mode`).
        - type: `string`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `current_deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_config`: `object (23 properties) | null`
        - type: `object (23 properties) | null`
      - `estimated_sleep_at`: `['integer', 'null']`
        - description: Estimated time (epoch millis) when the environment will go to sleep
        - type: `['integer', 'null']`
      - `https_redirect` *required*: `string`
        - description: An environment's HTTP→HTTPS redirect (`environments.https_redirect`).
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_preview` *required*: `boolean`
        - description: Indicates if this is a preview environment (auto-created per branch)
        - type: `boolean`
      - `last_activity_at`: `['integer', 'null']`
        - description: Last proxied request timestamp (epoch millis) for on-demand environments.
        - type: `['integer', 'null']`
      - `main_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `protected` *required*: `boolean`
        - description: When true, git pushes do NOT auto-deploy to this environment.
        - type: `boolean`
      - `sleeping` *required*: `boolean`
        - description: When true, the environment's containers are currently stopped due to
        - type: `boolean`
      - `slug` *required*: `string`
        - type: `string`
      - `subdomain` *required*: `string`
        - description: The host label stored for this environment (e.g.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}`

- operationId: `delete_environment`
- summary: Delete one environment of one project.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Environment deleted
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `409`: Environment delete refused, nothing deleted: a container or compose stack of the environment could not be stopped and removed (problem type `https://conusai.com/probs/environment-delete-blocked`), or a linked service's resource could not be deprovisioned; retry
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `428`: Recent MFA verification required
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/app-bindings`

- operationId: `create_binding`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `app_tenant_id` *required*: `string`
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `app_tenant_id` *required*: `string`
        - type: `string`
      - `binding_id` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `environment_uuid` *required*: `string`
        - type: `string`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `partition_major` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
  - `403`: Project administration permission refused
  - `404`: Environment unavailable in this project
  - `503`: Control plane unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/app-bindings/{binding_id}/revoke`

- operationId: `revoke_binding`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `binding_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Binding permanently revoked; data preserved
  - `403`: Project administration permission refused
  - `404`: No binding in this exact authority

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/app-bindings/{binding_id}/services/{service}/grant`

- operationId: `set_service_grant`
- tags: `App binding`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `binding_id` (path) *required*: `string`
  - `service` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `approved_scopes` *required*: `array<string>`
      - description: Exact scopes; no wildcard/foreign service or default approval.
      - type: `array<string>`
    - `expected_generation`: `['integer', 'null']`
      - description: Absent creates only; present compares the current monotonic generation.
      - type: `['integer', 'null']`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (3 properties)`
      - `approved_scopes` *required*: `array<string>`
        - type: `array<string>`
      - `generation` *required*: `integer`
        - type: `integer`
      - `revoked` *required*: `boolean`
        - type: `boolean`
  - `400`: Invalid or foreign scope
  - `403`: Current project administration required
  - `404`: Binding/service unavailable
  - `409`: Consent generation changed
  - `503`: Atomic consent/audit unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/domains`

- operationId: `get_environment_domains`
- summary: List the custom domains attached to one environment.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment domains
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/domains`

- operationId: `add_environment_domain`
- summary: Attach a custom domain to one environment.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `domain` *required*: `string`
      - type: `string`
    - `is_primary` *required*: `boolean`
      - type: `boolean`
- responses:
  - `201`: Domain attached
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `url` *required*: `string`
        - description: Full URL for this domain (e.g., <https://buildtolearndev-production.example.com>)
        - type: `string`
      - `verification`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `verified_at`: `['integer', 'null']`
        - description: When the domain's verification TXT record was last found
        - type: `['integer', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/domains/{domain_id}`

- operationId: `delete_environment_domain`
- summary: Detach a custom domain from one environment.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Domain detached
  - `401`: Unauthorized
  - `404`: Environment or domain not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/domains/{domain_id}/verify`

- operationId: `verify_environment_domain`
- summary: Verify an environment domain: look up its `_conusai-challenge` TXT record
and, when found, claim the name and start routing it (G1F, D6).
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `domain_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Domain verified; it now claims its hostname and routes
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `domain` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `url` *required*: `string`
        - description: Full URL for this domain (e.g., <https://buildtolearndev-production.example.com>)
        - type: `string`
      - `verification`: `object (2 properties) | null`
        - type: `object (2 properties) | null`
      - `verified_at`: `['integer', 'null']`
        - description: When the domain's verification TXT record was last found
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Below `EnvironmentsWrite` or the workspace member role
  - `404`: Environment or domain not found in this project
  - `409`: Another owner verified this hostname first (`urn:conusai:domains:hostname-claimed`)
  - `422`: The TXT record is not published (`urn:conusai:domains:verification-record-missing`, with `record_name` and `record_value`)
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/platform-aliases`

- operationId: `list`
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `aliases` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `canonical_url` *required*: `string`
        - type: `string`
  - `403`: Super admin required
  - `404`: Not found in selected project
  - `409`: Hostname already claimed

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/platform-aliases/{name}`

- operationId: `set`
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `403`: Super admin required
  - `404`: Not found in selected project
  - `409`: Hostname already claimed

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/platform-aliases/{name}`

- operationId: `remove`
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Removed
  - `403`: Super admin required
  - `404`: Not found in selected project
  - `409`: Hostname already claimed

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/platform-aliases/{name}/transfer`

- operationId: `transfer`
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `name` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `target_environment_id` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (5 properties)`
      - `domain` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `403`: Super admin required
  - `404`: Not found in selected project
  - `409`: Hostname already claimed

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/platform-services/{service}/readiness`

- operationId: `native_readiness`
- summary: Read-only current prerequisite facts for the exact deployment environment.
- tags: `Native service prerequisites`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
  - `service` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `api_range` *required*: `string`
      - description: Intended component API range; no claim about the installed version.
      - type: `string`
    - `app_scope`: `string`
      - description: Local app authorization realm, never a replacement for the Cloud project.
      - type: `string`
    - `channel`: `['string', 'null']`
      - description: Trusted Support channel public key; never a credential or tenant selector.
      - type: `['string', 'null']`
    - `identity_namespace`: `['string', 'null']`
      - description: Trusted Guides identity namespace; no end-user subject is observed.
      - type: `['string', 'null']`
    - `model`: `['string', 'null']`
      - description: Bounded trusted composition selector for AI configuration; never an identity/grant.
      - type: `['string', 'null']`
    - `operation`: `string | null`
      - type: `string | null`
    - `scopes` *required*: `array<string>`
      - type: `array<string>`
- responses:
  - `200`: Current safe facts; unknown never grants readiness
    - `application/json`:
      - type: `object (13 properties)`
      - `app_scope` *required*: `string`
        - description: Local app authorization realm, never a replacement for the Cloud project.
        - type: `string`
      - `authorization_checked_at` *required*: `string`
        - description: Fresh authorization time. It never refreshes an older component health observation.
        - type: `string`
      - `authorized` *required*: `string`
        - type: `string`
      - `compatible` *required*: `string`
        - type: `string`
      - `component` *required*: `object (14 properties)`
        - type: `object (14 properties)`
      - `dependencies_ready` *required*: `string`
        - type: `string`
      - `descriptor_digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_bound` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `organization_id` *required*: `integer`
        - type: `integer`
      - `policy_epoch`: `['integer', 'null']`
        - description: Current root-protected authenticated release policy epoch, not an invented registry generation.
        - type: `['integer', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `source_commit`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Deployment credential missing
  - `403`: Wrong credential kind or missing explicit permission
  - `404`: Foreign, unbound, deleted or unavailable project/environment
  - `503`: Evidence unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/promote`

- operationId: `promote_environment`
- summary: Point one environment's stable alias at a specific deployment.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `deployment_id` *required*: `integer`
      - description: Deployment ID to point the environment's stable alias at.
      - type: `integer`
- responses:
  - `200`: Alias promoted
    - `application/json`:
      - type: `object (2 properties)`
      - `deployment_id` *required*: `integer`
        - type: `integer`
      - `environment_id` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Environment or deployment not found in this project
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/settings`

- operationId: `update_environment_settings`
- summary: Update one environment's deployment settings.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (23 properties)`
    - `anti_affinity`: `['boolean', 'null']`
      - description: Anti-affinity: spread replicas across different nodes.
      - type: `['boolean', 'null']`
    - `attack_mode`: `string | null`
      - type: `string | null`
    - `automatic_deploy`: `['boolean', 'null']`
      - description: Enable/disable automatic deployments for this environment
      - type: `['boolean', 'null']`
    - `branch`: `['string', 'null']`
      - type: `['string', 'null']`
    - `cpu_limit`: `integer | string | null`
      - type: `integer | string | null`
    - `cpu_request`: `['integer', 'null']`
      - description: Minimum (request) CPU in microcores. Send JSON `null` to clear (no request).
      - type: `['integer', 'null']`
    - `cross_architecture_builds`: `['boolean', 'null']`
      - description: Build one image per architecture the eligible nodes run, overriding the
      - type: `['boolean', 'null']`
    - `exposed_port`: `['integer', 'null']`
      - description: Port exposed by the container (overrides project-level port for this environment)
      - type: `['integer', 'null']`
    - `https_redirect`: `string | null`
      - type: `string | null`
    - `idle_timeout_seconds`: `['integer', 'null']`
      - description: Seconds of inactivity before stopping containers (60-86400). Default: 300.
      - type: `['integer', 'null']`
    - `memory_limit`: `integer | string | null`
      - type: `integer | string | null`
    - `memory_request`: `['integer', 'null']`
      - description: Minimum (request) memory in MB. Send JSON `null` to clear (no request).
      - type: `['integer', 'null']`
    - `on_demand`: `['boolean', 'null']`
      - description: Enable on-demand mode (scale-to-zero). Containers are stopped after
      - type: `['boolean', 'null']`
    - `password`: `['string', 'null']`
      - description: Set a password to protect this environment. The proxy will show an HTML
      - type: `['string', 'null']`
    - `performance_metrics_enabled`: `['boolean', 'null']`
      - description: Enable/disable performance metrics collection
      - type: `['boolean', 'null']`
    - `protected`: `['boolean', 'null']`
      - description: When true, git pushes do NOT auto-deploy to this environment.
      - type: `['boolean', 'null']`
    - `replicas`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `security`: `object (7 properties) | null`
      - type: `object (7 properties) | null`
    - `session_recording_enabled`: `['boolean', 'null']`
      - description: Enable/disable session recording
      - type: `['boolean', 'null']`
    - `target_labels`: `any`
      - description: Label selector for node-based scheduling (overrides project-level setting).
      - type: `any`
    - `target_nodes`: `['array', 'null']`
      - description: Optional list of node IDs to deploy to (overrides project-level setting)
      - type: `['array', 'null']`
    - `token_permissions`: `['array', 'null']`
      - description: Image-deployment scope requests, not approvals. Absent leaves unchanged;
      - type: `['array', 'null']`
    - `wake_timeout_seconds`: `['integer', 'null']`
      - description: Max seconds to wait for containers to start on wake (5-120). Default: 30.
      - type: `['integer', 'null']`
- responses:
  - `200`: Settings updated
    - `application/json`:
      - type: `object (18 properties)`
      - `attack_mode` *required*: `string`
        - description: An environment's CAPTCHA attack-mode setting (`environments.attack_mode`).
        - type: `string`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `current_deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_config`: `object (23 properties) | null`
        - type: `object (23 properties) | null`
      - `estimated_sleep_at`: `['integer', 'null']`
        - description: Estimated time (epoch millis) when the environment will go to sleep
        - type: `['integer', 'null']`
      - `https_redirect` *required*: `string`
        - description: An environment's HTTP→HTTPS redirect (`environments.https_redirect`).
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_preview` *required*: `boolean`
        - description: Indicates if this is a preview environment (auto-created per branch)
        - type: `boolean`
      - `last_activity_at`: `['integer', 'null']`
        - description: Last proxied request timestamp (epoch millis) for on-demand environments.
        - type: `['integer', 'null']`
      - `main_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `protected` *required*: `boolean`
        - description: When true, git pushes do NOT auto-deploy to this environment.
        - type: `boolean`
      - `sleeping` *required*: `boolean`
        - description: When true, the environment's containers are currently stopped due to
        - type: `boolean`
      - `slug` *required*: `string`
        - type: `string`
      - `subdomain` *required*: `string`
        - description: The host label stored for this environment (e.g.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/sleep`

- operationId: `sleep_environment`
- summary: Put an on-demand environment to sleep.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment put to sleep
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/subdomain`

- operationId: `update_environment_subdomain`
- summary: Change one environment's subdomain.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `subdomain` *required*: `string`
      - description: New subdomain label. Must be a DNS-safe slug (lowercase letters,
      - type: `string`
- responses:
  - `200`: Subdomain updated
    - `application/json`:
      - type: `object (18 properties)`
      - `attack_mode` *required*: `string`
        - description: An environment's CAPTCHA attack-mode setting (`environments.attack_mode`).
        - type: `string`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `current_deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `deployment_config`: `object (23 properties) | null`
        - type: `object (23 properties) | null`
      - `estimated_sleep_at`: `['integer', 'null']`
        - description: Estimated time (epoch millis) when the environment will go to sleep
        - type: `['integer', 'null']`
      - `https_redirect` *required*: `string`
        - description: An environment's HTTP→HTTPS redirect (`environments.https_redirect`).
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_preview` *required*: `boolean`
        - description: Indicates if this is a preview environment (auto-created per branch)
        - type: `boolean`
      - `last_activity_at`: `['integer', 'null']`
        - description: Last proxied request timestamp (epoch millis) for on-demand environments.
        - type: `['integer', 'null']`
      - `main_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `protected` *required*: `boolean`
        - description: When true, git pushes do NOT auto-deploy to this environment.
        - type: `boolean`
      - `sleeping` *required*: `boolean`
        - description: When true, the environment's containers are currently stopped due to
        - type: `boolean`
      - `slug` *required*: `string`
        - type: `string`
      - `subdomain` *required*: `string`
        - description: The host label stored for this environment (e.g.
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{env_id}/wake`

- operationId: `wake_environment`
- summary: Wake a sleeping on-demand environment.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `env_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment woken
  - `401`: Unauthorized
  - `404`: Environment not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/asset-cache`

- operationId: `purge_environment_asset_cache`
- summary: Purge cached static assets for one environment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment asset cache purged
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/container-logs`

- operationId: `get_container_logs`
- summary: Stream an environment's container logs over a `WebSocket`.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `start_date` (query): `integer`
  - `end_date` (query): `integer`
  - `tail` (query): `string`
  - `container_name` (query): `string`
  - `timestamps` (query): `boolean`
  - `follow` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `101`: WebSocket connection established for streaming container logs
  - `400`: Not a server-type project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/container-logs/history`

- operationId: `get_container_log_history`
- summary: Read an environment's recent container output over plain HTTP, bounded.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `tail` (query): `integer`
  - `container_name` (query): `string`
  - `start_date` (query): `integer`
  - `end_date` (query): `integer`
  - `timestamps` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `200`: Recent container output, bounded by lines, bytes and time
    - `application/json`:
      - type: `object (6 properties)`
      - `container_name`: `['string', 'null']`
        - description: The container asked for, when one was named.
        - type: `['string', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `lines` *required*: `array<string>`
        - description: Log lines, oldest first, without their trailing newline.
        - type: `array<string>`
      - `max_bytes` *required*: `integer`
        - description: The byte bound applied to this request.
        - type: `integer`
      - `max_lines` *required*: `integer`
        - description: The line bound applied to this request.
        - type: `integer`
      - `truncated` *required*: `boolean`
        - description: A bound (lines, bytes or time) ended the read before the log did.
        - type: `boolean`
  - `400`: Not a server-type project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment, deployment or container not found in this workspace
  - `502`: The log stream failed mid-read

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers`

- operationId: `list_containers`
- summary: List the running containers of an environment.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Containers in the environment
    - `application/json`:
      - type: `object (2 properties)`
      - `containers` *required*: `array<object (17 properties)>`
        - type: `array<object (17 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `400`: Not a server-type project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}`

- operationId: `get_container_detail`
- summary: Read one container's full detail record.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container details
    - `application/json`:
      - type: `object (23 properties)`
      - `container_id` *required*: `string`
        - type: `string`
      - `container_name` *required*: `string`
        - type: `string`
      - `container_port` *required*: `integer`
        - description: Port inside the container
        - type: `integer`
      - `cpu_limit_cores`: `['number', 'null']`
        - description: CPU limit in whole cores (e.g. 1.0). None when no limit is configured.
        - type: `['number', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `deployed_at` *required*: `string`
        - type: `string`
      - `deployment_id` *required*: `integer`
        - type: `integer`
      - `environment_variables` *required*: `array<object (3 properties)>`
        - description: Environment variables (sensitive values masked)
        - type: `array<object (3 properties)>`
      - `error_message`: `['string', 'null']`
        - description: Free-form error string from Docker's container state on exit.
        - type: `['string', 'null']`
      - `exit_code`: `['integer', 'null']`
        - description: Process exit code reported by Docker. None while still running.
        - type: `['integer', 'null']`
      - `exit_reason`: `['string', 'null']`
        - description: Human-readable reason the container exited.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - description: When the container exited (Docker's `FinishedAt`). None while running.
        - type: `['string', 'null']`
      - `host_port`: `['integer', 'null']`
        - description: Port on the host machine
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `image_name` *required*: `string`
        - type: `string`
      - `oom_killed` *required*: `boolean`
        - description: True when Docker's OOM killer terminated the container.
        - type: `boolean`
      - `ready_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `resource_limits`: `object (4 properties) | null`
        - type: `object (4 properties) | null`
      - `restart_count`: `['integer', 'null']`
        - description: Container restart count from Docker
        - type: `['integer', 'null']`
      - `service_name`: `['string', 'null']`
        - description: Compose service name (e.g. "web", "redis"). None for single-container deployments.
        - type: `['string', 'null']`
      - `service_url`: `['string', 'null']`
        - description: Per-service URL for compose deployments
        - type: `['string', 'null']`
      - `started_at`: `['string', 'null']`
        - description: When the container's main process most recently started.
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/environment/{key}/reveal`

- operationId: `reveal_container_environment_value`
- summary: Reveal one masked environment value of a deployed container.
- description: The container detail withholds every variable that
[`conusai_security_core::is_sensitive_variable`] classifies as a secret, by
its name or by its value. This is the discrete, audited way to read one
back, guarded like the managed-service parameter reveal
(`conusai-providers` `reveal_service_parameter`): an interactive browser
session (an API key, CLI or deployment token gets 401), the workspace admin
role, a fresh step-up (428 `STEP_UP_REQUIRED` otherwise), and an audit row
under the container's organization written before the answer. A reveal that
cannot be audited is refused. A variable the detail does not mask is not
revealable here (404): its value is already in the detail.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
  - `key` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The revealed value
    - `application/json`:
      - type: `object (2 properties)`
      - `key` *required*: `string`
        - type: `string`
      - `value` *required*: `string`
        - type: `string`
  - `401`: Authenticated browser session required
  - `403`: Workspace admin role required
  - `404`: Project, environment, container or masked variable not found in this workspace
  - `428`: Fresh session verification required
  - `500`: Authorization, container inspection or audit failed

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/exec`

- operationId: `exec_command`
- summary: Run a one-shot command inside a container.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `command` *required*: `array<string>`
      - description: Command to execute (e.g. ["sh", "-c", "ls -la"])
      - type: `array<string>`
    - `timeout_seconds`: `['integer', 'null']`
      - description: Timeout in seconds (default: 30, max: 300)
      - type: `['integer', 'null']`
- responses:
  - `200`: Command executed
    - `application/json`:
      - type: `object (4 properties)`
      - `exit_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `stderr` *required*: `string`
        - type: `string`
      - `stdout` *required*: `string`
        - type: `string`
      - `truncated` *required*: `boolean`
        - description: stdout or stderr was longer than 1 MiB and was cut there (F361b).
        - type: `boolean`
  - `400`: Empty command, or exec not enabled for this environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `428`: Fresh session verification required
  - `500`: Exec failed, or it could not be audited and did not run
  - `504`: Command timed out

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/logs`

- operationId: `get_container_logs_by_id`
- summary: Stream one named container's logs over a `WebSocket`.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
  - `start_date` (query): `integer`
  - `end_date` (query): `integer`
  - `tail` (query): `string`
  - `container_name` (query): `string`
  - `timestamps` (query): `boolean`
  - `follow` (query): `boolean`
- requestBody: _(none)_
- responses:
  - `101`: WebSocket connection established for streaming container logs
  - `400`: Not a server-type project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/metrics`

- operationId: `get_container_metrics`
- summary: Read one container's current resource metrics.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container metrics
    - `application/json`:
      - type: `object (10 properties)`
      - `container_id` *required*: `string`
        - type: `string`
      - `container_name` *required*: `string`
        - type: `string`
      - `cpu_limit_cores`: `['number', 'null']`
        - description: CPU limit in whole cores (e.g. 1.0). None = no limit.
        - type: `['number', 'null']`
      - `cpu_percent` *required*: `number`
        - description: CPU usage as a multi-core percentage (Docker convention: 200 = 2 cores
        - type: `number`
      - `memory_bytes` *required*: `integer`
        - description: Memory usage in bytes
        - type: `integer`
      - `memory_limit_bytes`: `['integer', 'null']`
        - description: Memory limit in bytes (if set)
        - type: `['integer', 'null']`
      - `memory_percent`: `['number', 'null']`
        - description: Memory usage percentage (0-100) if limit is set
        - type: `['number', 'null']`
      - `network_rx_bytes` *required*: `integer`
        - description: Network bytes received
        - type: `integer`
      - `network_tx_bytes` *required*: `integer`
        - description: Network bytes transmitted
        - type: `integer`
      - `timestamp` *required*: `string`
        - description: Timestamp of metrics collection
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/metrics/stream`

- operationId: `stream_container_metrics`
- summary: Stream one container's resource metrics over Server-Sent Events.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
  - `interval` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Metrics stream established (Server-Sent Events)
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/restart`

- operationId: `restart_container`
- summary: Restart a container.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container restarted
    - `application/json`:
      - type: `object (5 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `container_id` *required*: `string`
        - type: `string`
      - `container_name` *required*: `string`
        - type: `string`
      - `message` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/start`

- operationId: `start_container`
- summary: Start a stopped container.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container started
    - `application/json`:
      - type: `object (5 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `container_id` *required*: `string`
        - type: `string`
      - `container_name` *required*: `string`
        - type: `string`
      - `message` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/containers/{container_id}/stop`

- operationId: `stop_container`
- summary: Stop a running container.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `container_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container stopped
    - `application/json`:
      - type: `object (5 properties)`
      - `action` *required*: `string`
        - type: `string`
      - `container_id` *required*: `string`
        - type: `string`
      - `container_name` *required*: `string`
        - type: `string`
      - `message` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/crons`

- operationId: `get_environment_crons`
- summary: List an environment's configured cron jobs.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cron jobs in the environment
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/crons/{cron_id}`

- operationId: `get_cron_by_id`
- summary: Read one cron job.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `cron_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cron job details
    - `application/json`:
      - type: `object (9 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `deleted_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `next_run`: `['string', 'null']`
        - type: `['string', 'null']`
      - `path` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `schedule` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or cron job not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/crons/{cron_id}/executions`

- operationId: `get_cron_executions`
- summary: List one cron job's execution history.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `cron_id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cron job executions
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or cron job not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/deploy/image`

- operationId: `deploy_from_image`
- summary: Deploy an environment from a pre-built Docker image reference.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `external_image_id`: `['integer', 'null']`
      - description: External image ID; if given without `image_ref`, the ref is fetched from it.
      - type: `['integer', 'null']`
    - `health_check_path`: `['string', 'null']`
      - description: Optional HTTP health-check path override (e.g. "/api/healthz").
      - type: `['string', 'null']`
    - `image_ref`: `['string', 'null']`
      - description: Docker image reference (e.g., "quay.io/org/app:v1.0"); required if `external_image_id` is not provided
      - type: `['string', 'null']`
    - `metadata`: `any`
      - description: Optional deployment metadata
      - type: `any`
- responses:
  - `202`: Deployment started
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/deploy/image-upload`

- operationId: `deploy_from_image_upload`
- summary: Deploy an environment from an uploaded Docker image tarball.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
  - `tag` (query): `['string', 'null']`
  - `health_check_path` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `202`: Image imported and deployment started
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `400`: Invalid request or unsupported format
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `413`: Image tarball too large
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/deploy/static`

- operationId: `deploy_from_static`
- summary: Deploy an environment from an uploaded static bundle.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `health_check_path`: `['string', 'null']`
      - description: Optional HTTP health-check path override (e.g. "/api/healthz").
      - type: `['string', 'null']`
    - `metadata`: `any`
      - description: Optional deployment metadata
      - type: `any`
    - `static_bundle_id` *required*: `integer`
      - description: Static bundle ID (required)
      - type: `integer`
- responses:
  - `202`: Deployment started
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - type: `string`
      - `state` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or bundle not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/environments/{environment_id}/teardown`

- operationId: `teardown_environment`
- summary: Tear an environment and every active deployment in it down.
- description: The legacy route spells this capture `{env_id}`; the v1 route spells it
`{environment_id}` to match every other environment route already mounted
under [`PROJECT_SCOPE_PREFIX`]. That is not cosmetic: axum panics at
router-build time when two routes name the same path position differently,
so `{env_id}` here would be a startup crash, not a doc inconsistency.
The v1 endpoint projection projects the legacy spelling forward — the
generator derives its target mechanically from the legacy path and never
reads this file — so the projection and this route disagree on the
parameter's *name* only, never on its position or meaning.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Environment torn down
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or environment not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-alert-rules`

- operationId: `list_alert_rules`
- summary: List the error alert rules of one path-scoped project.
- tags: `error-alert-rules-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of alert rules
    - `application/json`:
      - type: `array<object (12 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-alert-rules`

- operationId: `create_alert_rule`
- summary: Create an error alert rule in one path-scoped project.
- tags: `error-alert-rules-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `action_interval_minutes`: `integer`
      - description: Minimum minutes between notifications for one rule and group, 5..=43200
      - type: `integer`
    - `enabled`: `boolean`
      - type: `boolean`
    - `environment_filter`: `['integer', 'null']`
      - description: Optional environment ID to filter alerts
      - type: `['integer', 'null']`
    - `error_level_filter`: `['string', 'null']`
      - description: Optional error type/level filter
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `notification_priority`: `string`
      - description: Notification priority: Low, Normal, High, Critical
      - type: `string`
    - `trigger_config`: `any`
      - description: Trigger-specific configuration (e.g. `count` / `window_minutes` for frequency triggers)
      - type: `any`
    - `trigger_type` *required*: `string`
      - description: Trigger type: `new_issue`, `regressed`, frequency, `new_user`, `user_count`, `status_change`
      - type: `string`
- responses:
  - `201`: Alert rule created
    - `application/json`:
      - type: `object (12 properties)`
      - `action_interval_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_filter`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_level_filter`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `notification_priority` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-alert-rules/{rule_id}`

- operationId: `get_alert_rule`
- summary: Read one error alert rule of one path-scoped project.
- tags: `error-alert-rules-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `rule_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Alert rule details
    - `application/json`:
      - type: `object (12 properties)`
      - `action_interval_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_filter`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_level_filter`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `notification_priority` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Alert rule not found in this project
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-alert-rules/{rule_id}`

- operationId: `update_alert_rule`
- summary: Update one error alert rule of one path-scoped project.
- tags: `error-alert-rules-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `rule_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `action_interval_minutes`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `environment_filter`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `error_level_filter`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `notification_priority`: `['string', 'null']`
      - type: `['string', 'null']`
    - `trigger_config`: `any`
      - type: `any`
    - `trigger_type`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Alert rule updated
    - `application/json`:
      - type: `object (12 properties)`
      - `action_interval_minutes` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_filter`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_level_filter`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `notification_priority` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `trigger_config` *required*: `any`
        - type: `any`
      - `trigger_type` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Alert rule not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-alert-rules/{rule_id}`

- operationId: `delete_alert_rule`
- summary: Delete one error alert rule of one path-scoped project.
- tags: `error-alert-rules-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `rule_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Alert rule deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Alert rule not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/error-time-series`

- operationId: `get_error_time_series`
- summary: Error time series for one path-scoped project.
- tags: `error-tracking-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
  - `bucket` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Error time series data
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/events/{event_id}`

- operationId: `get_event`
- summary: Get one event by its Sentry UUID.
- tags: `error-tracking-v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `event_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Event details by UUID
    - `application/json`:
      - type: `object (10 properties)`
      - `data`: `any`
        - type: `any`
      - `error_group_id` *required*: `integer`
        - type: `integer`
      - `event_id` *required*: `string`
        - type: `string`
      - `exception_type` *required*: `string`
        - type: `string`
      - `exception_value`: `['string', 'null']`
        - type: `['string', 'null']`
      - `received_at` *required*: `string`
        - type: `string`
      - `release`: `['string', 'null']`
        - type: `['string', 'null']`
      - `session_id`: `['string', 'null']`
        - type: `['string', 'null']`
      - `timestamp` *required*: `string`
        - type: `string`
      - `trace_id`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Event not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/issues`

- operationId: `list_issues`
- summary: List issues of a project with keyset pagination and filtering.
- tags: `error-tracking-v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `cursor` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `query` (query): `['string', 'null']`
  - `status` (query): `['string', 'null']`
  - `substatus` (query): `['string', 'null']`
  - `release` (query): `['string', 'null']`
  - `environment_id` (query): `['integer', 'null']`
  - `from` (query): `['string', 'null']`
  - `to` (query): `['string', 'null']`
  - `sort` (query): `string | null`
  - `response_format` (query): `string | null`
- requestBody: _(none)_
- responses:
  - `200`: List of issues (concise by default, detailed if requested)
    - `application/json`:
      - type: `object (3 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `422`: Invalid cursor
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/issues/{issue_id}`

- operationId: `get_issue`
- summary: Get one issue by ID with optional included associations (events, stats, breadcrumbs).
- tags: `error-tracking-v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `issue_id` (path) *required*: `integer`
  - `include` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Detailed issue details
    - `application/json`:
      - type: `object (21 properties)`
      - `breadcrumbs`: `any`
        - type: `any`
      - `count` *required*: `integer`
        - type: `integer`
      - `culprit` *required*: `string`
        - type: `string`
      - `current_hour_count` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<string>`
        - type: `array<string>`
      - `escalation_threshold_per_hour`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `events`: `['array', 'null']`
        - type: `['array', 'null']`
      - `first_seen` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_seen` *required*: `string`
        - type: `string`
      - `latest_event`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `level` *required*: `string`
        - type: `string`
      - `release_last_seen`: `['string', 'null']`
        - type: `['string', 'null']`
      - `resolved_in_release`: `['string', 'null']`
        - type: `['string', 'null']`
      - `short_id` *required*: `string`
        - type: `string`
      - `stats`: `object (1 properties) | null`
        - type: `object (1 properties) | null`
      - `status` *required*: `string`
        - type: `string`
      - `substatus` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
      - `users_affected` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Issue not found
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/issues/{issue_id}`

- operationId: `patch_issue`
- summary: Apply a status transition or metadata update to one issue.
- tags: `error-tracking-v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `issue_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `action` *required*: `string`
      - type: `string`
    - `assignee`: `['string', 'null']`
      - type: `['string', 'null']`
    - `release`: `['string', 'null']`
      - type: `['string', 'null']`
    - `until`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Issue updated successfully
    - `application/json`:
      - type: `object (21 properties)`
      - `breadcrumbs`: `any`
        - type: `any`
      - `count` *required*: `integer`
        - type: `integer`
      - `culprit` *required*: `string`
        - type: `string`
      - `current_hour_count` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<string>`
        - type: `array<string>`
      - `escalation_threshold_per_hour`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `events`: `['array', 'null']`
        - type: `['array', 'null']`
      - `first_seen` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_seen` *required*: `string`
        - type: `string`
      - `latest_event`: `object (7 properties) | null`
        - type: `object (7 properties) | null`
      - `level` *required*: `string`
        - type: `string`
      - `release_last_seen`: `['string', 'null']`
        - type: `['string', 'null']`
      - `resolved_in_release`: `['string', 'null']`
        - type: `['string', 'null']`
      - `short_id` *required*: `string`
        - type: `string`
      - `stats`: `object (1 properties) | null`
        - type: `object (1 properties) | null`
      - `status` *required*: `string`
        - type: `string`
      - `substatus` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
      - `users_affected` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Issue not found
  - `422`: Illegal status transition
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/issues/{issue_id}/events`

- operationId: `list_issue_events`
- summary: List events of one issue with keyset cursor pagination on `(timestamp, event_id)`.
- tags: `error-tracking-v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `issue_id` (path) *required*: `integer`
  - `cursor` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Paginated list of issue events
    - `application/json`:
      - type: `object (4 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Issue not found
  - `422`: Invalid cursor
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/outcomes`

- operationId: `get_error_outcomes`
- summary: GET {PROJECT}/errors/outcomes
- tags: `Error Tracking v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `from` (query): `['string', 'null']`
  - `to` (query): `['string', 'null']`
  - `group_by` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Outcomes aggregated by category/reason/source
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found
  - `422`: Invalid group_by column
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/settings`

- operationId: `get_error_tracking_settings`
- summary: GET {PROJECT}/errors/settings
- tags: `Error Tracking v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Project error tracking settings
    - `application/json`:
      - type: `object (3 properties)`
      - `event_retention_days` *required*: `integer`
        - type: `integer`
      - `rate_limit_per_minute`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `send_default_pii` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/errors/settings`

- operationId: `put_error_tracking_settings`
- summary: PUT {PROJECT}/errors/settings
- tags: `Error Tracking v2`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `event_retention_days`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `rate_limit_per_minute`: `['integer', 'null']`
      - description: Per-DSN ingest budget. Absent = unchanged; `null` = clear (unlimited —
      - type: `['integer', 'null']`
    - `send_default_pii`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
- responses:
  - `200`: Updated project error tracking settings
    - `application/json`:
      - type: `object (3 properties)`
      - `event_retention_days` *required*: `integer`
        - type: `integer`
      - `rate_limit_per_minute`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `send_default_pii` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Forbidden
  - `404`: Project not found
  - `422`: Validation error (e.g. retention floor/ceiling violation)
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events`

- operationId: `get_events_count`
- summary: Event counts for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `limit` (query): `integer`
  - `custom_events_only` (query): `boolean`
  - `aggregation_level` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved event counts
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/breakdown`

- operationId: `get_event_type_breakdown`
- summary: Event-type breakdown for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `aggregation_level` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved event type breakdown
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/ingest`

- operationId: `record_console_event`
- summary: Record one analytics event into a project from the console.
- description: This is the **authenticated** ingest path used by the console and by
server-side app backends; it is not the public browser-SDK collector, which
stays at `POST /_conusai/event` and is deliberately not mirrored here.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `deployment_id` *required*: `integer`
      - description: Deployment ID to attribute the event to
      - type: `integer`
    - `environment_id` *required*: `integer`
      - description: Environment ID to attribute the event to
      - type: `integer`
    - `event_data`: `any`
      - description: Arbitrary JSON event data
      - type: `any`
    - `event_name` *required*: `string`
      - description: Event name (e.g. "purchase", "signup", custom event names)
      - type: `string`
    - `request_path`: `string`
      - description: Page path context (defaults to "/")
      - type: `string`
    - `request_query`: `string`
      - description: Query string context
      - type: `string`
    - `session_id`: `['string', 'null']`
      - description: Encrypted `_conusai_sid` cookie value from the user's browser
      - type: `['string', 'null']`
    - `visitor_id`: `['string', 'null']`
      - description: Encrypted `_conusai_visitor_id` cookie value from the user's browser
      - type: `['string', 'null']`
- responses:
  - `200`: Event recorded successfully
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/properties/breakdown`

- operationId: `get_property_breakdown`
- summary: Property breakdown for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `group_by` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `event_name` (query): `string`
  - `aggregation_level` (query): `string`
  - `limit` (query): `integer`
  - `filter_country` (query): `string`
  - `filter_region` (query): `string`
  - `filter_browser` (query): `string`
  - `filter_os` (query): `string`
  - `filter_channel` (query): `string`
  - `filter_referrer` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved property breakdown
    - `application/json`:
      - type: `object (3 properties)`
      - `items` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `property` *required*: `string`
        - type: `string`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/properties/timeline`

- operationId: `get_property_timeline`
- summary: Property timeline for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `group_by` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `event_name` (query): `string`
  - `aggregation_level` (query): `string`
  - `bucket_size` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved property timeline
    - `application/json`:
      - type: `object (3 properties)`
      - `bucket_size` *required*: `string`
        - type: `string`
      - `items` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `property` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/timeline`

- operationId: `get_events_timeline`
- summary: Event timeline for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `event_name` (query): `string`
  - `bucket_size` (query): `string`
  - `aggregation_level` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved event timeline
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/events/unique`

- operationId: `get_unique_events`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Unique event types retrieved successfully
    - `application/json`:
      - type: `object (4 properties)`
      - `events` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/external-images`

- operationId: `list_remote_external_images`
- summary: List a project's persisted external images.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: External images for the project
    - `application/json`:
      - type: `object (4 properties)`
      - `data` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/external-images`

- operationId: `register_external_image`
- summary: Register an external Docker image as a persisted row.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `digest`: `['string', 'null']`
      - description: Image digest (sha256:...)
      - type: `['string', 'null']`
    - `image_ref` *required*: `string`
      - description: Docker image reference (e.g., "quay.io/org/app:v1.0")
      - type: `string`
    - `metadata`: `any`
      - description: Additional metadata
      - type: `any`
    - `tag`: `['string', 'null']`
      - description: Image tag
      - type: `['string', 'null']`
- responses:
  - `201`: Image registered
    - `application/json`:
      - type: `object (9 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `image_ref` *required*: `string`
        - type: `string`
      - `metadata`: `any`
        - type: `any`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/external-images/{image_id}`

- operationId: `get_remote_external_image`
- summary: Read one persisted external image.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `image_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Image details
    - `application/json`:
      - type: `object (9 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `image_ref` *required*: `string`
        - type: `string`
      - `metadata`: `any`
        - type: `any`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `size_bytes`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or image not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/external-images/{image_id}`

- operationId: `delete_external_image`
- summary: Delete a persisted external image.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `image_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Image deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or image not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/favicon`

- operationId: `get_project_favicon`
- summary: Get the favicon of the addressed project's production deployment.
- description: Same shared body as the legacy `/projects/{id}/favicon`
(`super::favicon::get_project_favicon_in_scope`); only the scope proof
differs. The project id the favicon cache is keyed by comes from the
resolved [`ProjectScope`], never from a caller-chosen segment, so a
cross-tenant request 404s in the extractor before the cache is touched.

A read, so no P2.1 role floor beyond the membership the scope resolver
already enforced — same as [`get_project`].
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Project favicon (image bytes)
  - `401`: Unauthorized
  - `404`: Project not found in this workspace, or no reachable favicon

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels`

- operationId: `list_funnels`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Funnels retrieved successfully
    - `application/json`:
      - type: `array<object (6 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels`

- operationId: `create_funnel`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `steps` *required*: `array<object (2 properties)>`
      - type: `array<object (2 properties)>`
- responses:
  - `201`: Funnel created successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `funnel_id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels/preview`

- operationId: `preview_funnel_metrics`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `country_code` (query): `string`
  - `start_date` (query): `string`
  - `end_date` (query): `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `steps` *required*: `array<object (2 properties)>`
      - type: `array<object (2 properties)>`
- responses:
  - `200`: Funnel metrics preview
    - `application/json`:
      - type: `object (6 properties)`
      - `average_completion_time_seconds` *required*: `number`
        - type: `number`
      - `funnel_id` *required*: `integer`
        - type: `integer`
      - `funnel_name` *required*: `string`
        - type: `string`
      - `overall_conversion_rate` *required*: `number`
        - type: `number`
      - `step_conversions` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `total_entries` *required*: `integer`
        - type: `integer`
  - `400`: Bad request
  - `401`: Unauthorized
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels/{funnel_id}`

- operationId: `update_funnel`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `funnel_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `steps` *required*: `array<object (2 properties)>`
      - type: `array<object (2 properties)>`
- responses:
  - `200`: Funnel updated successfully
  - `400`: Bad request
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Funnel not found
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels/{funnel_id}`

- operationId: `delete_funnel`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `funnel_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Funnel deleted successfully
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Funnel not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/funnels/{funnel_id}/metrics`

- operationId: `get_funnel_metrics`
- tags: `Funnels v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `funnel_id` (path) *required*: `integer`
  - `environment_id` (query): `integer`
  - `country_code` (query): `string`
  - `start_date` (query): `string`
  - `end_date` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Funnel metrics retrieved successfully
    - `application/json`:
      - type: `object (6 properties)`
      - `average_completion_time_seconds` *required*: `number`
        - type: `number`
      - `funnel_id` *required*: `integer`
        - type: `integer`
      - `funnel_name` *required*: `string`
        - type: `string`
      - `overall_conversion_rate` *required*: `number`
        - type: `number`
      - `step_conversions` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `total_entries` *required*: `integer`
        - type: `integer`
  - `400`: Bad request
  - `401`: Unauthorized
  - `404`: Funnel not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/git`

- operationId: `update_git_settings`
- summary: Update a project's Git settings.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `directory` *required*: `string`
      - type: `string`
    - `git_provider_connection_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `git_url`: `['string', 'null']`
      - description: Git clone URL for public repositories
      - type: `['string', 'null']`
    - `is_public_repo`: `['boolean', 'null']`
      - description: Whether this is a public repository (no git provider connection needed)
      - type: `['boolean', 'null']`
    - `main_branch` *required*: `string`
      - type: `string`
    - `preset`: `['string', 'null']`
      - type: `['string', 'null']`
    - `preset_config`: `object (2 properties) | object | object (4 properties) | null`
      - type: `object (2 properties) | object | object (4 properties) | null`
    - `repo_name` *required*: `string`
      - type: `string`
    - `repo_owner` *required*: `string`
      - type: `string`
- responses:
  - `200`: Git settings updated
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid git configuration or branch does not exist
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/gitlab/reinstall-webhook`

- operationId: `reinstall_gitlab_webhook`
- summary: Reinstall the GitLab webhook for a project.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Webhook reinstalled
    - `application/json`:
      - type: `object (2 properties)`
      - `hook_id` *required*: `integer`
        - description: The new GitLab hook ID that was installed.
        - type: `integer`
      - `message` *required*: `string`
        - description: Human-readable status message.
        - type: `string`
  - `400`: Project is not connected to a GitLab repository
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/guides/mcp/drafts`

- operationId: `guides_create_draft`
- summary: Create a guide draft (`{key, content}`, validated against
`guide.schema.json`); it is not published.
- tags: `Guides`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object`
- responses:
  - `201`: The draft guide
    - `application/json`:
      - type: `object`
  - `400`: Malformed request
  - `401`: Authentication required
  - `403`: Requires a session with guides:write
  - `409`: A guide with this key exists
  - `422`: The content is invalid

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/guides/mcp/guides`

- operationId: `guides_list_guides`
- summary: List the project's guides (summaries; no content).
- tags: `Guides`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `kind` (query): `string`
  - `environment` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Guide summaries
    - `application/json`:
      - type: `object`
  - `401`: Authentication required
  - `403`: Requires a session with guides:read
  - `404`: Project unavailable in the caller's scope

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/guides/mcp/guides/{id}/stats`

- operationId: `guides_get_stats`
- summary: One guide's aggregate stats (no end-user data).
- tags: `Guides`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `environment` (query): `string`
  - `version` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Eligible, started, completed and dismissed counts and rates
    - `application/json`:
      - type: `object`
  - `401`: Authentication required
  - `403`: Requires guides:read
  - `404`: Guide unavailable in the caller's scope

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/has-events`

- operationId: `has_analytics_events`
- summary: Whether one project has ever received an analytics event.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved has-events flag
    - `application/json`:
      - type: `object (1 properties)`
      - `has_events` *required*: `boolean`
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/hourly-visits`

- operationId: `get_hourly_visits`
- summary: Hourly visit timeline for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `aggregation_level` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved hourly visits
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/images`

- operationId: `list_external_images`
- summary: List the in-memory external images registered for a project.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: External images for the project
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/images/push`

- operationId: `push_external_image`
- summary: Push an external Docker image reference into the in-memory registry.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `image_ref` *required*: `string`
      - type: `string`
    - `metadata`: `any`
      - type: `any`
- responses:
  - `201`: Image pushed
    - `application/json`:
      - type: `object (5 properties)`
      - `digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `image_ref` *required*: `string`
        - type: `string`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `size`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/images/{image_id}`

- operationId: `get_external_image`
- summary: Read one in-memory external image.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `image_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Image details
    - `application/json`:
      - type: `object (5 properties)`
      - `digest`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `image_ref` *required*: `string`
        - type: `string`
      - `pushed_at` *required*: `string`
        - type: `string`
      - `size`: `['integer', 'null']`
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or image not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents`

- operationId: `list_incidents`
- summary: List the incidents of one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `status` (query): `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Incidents in the project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents`

- operationId: `create_incident`
- summary: Open an incident on one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `environment_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `monitor_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `severity` *required*: `string`
      - type: `string`
    - `title` *required*: `string`
      - type: `string`
- responses:
  - `201`: Incident created
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `monitor_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `resolved_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `severity` *required*: `string`
        - type: `string`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents/bucketed`

- operationId: `get_bucketed_incidents`
- summary: Bucketed incident series for one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `interval` (query): `string`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Bucketed incident data
    - `application/json`:
      - type: `object (4 properties)`
      - `buckets` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `interval` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
  - `400`: Invalid parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents/{incident_id}`

- operationId: `get_incident`
- summary: Read one incident of one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `incident_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Incident details
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `monitor_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `resolved_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `severity` *required*: `string`
        - type: `string`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Incident not found in this project
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents/{incident_id}/status`

- operationId: `update_incident_status`
- summary: Move one incident to a new status.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `incident_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `message` *required*: `string`
      - type: `string`
    - `status` *required*: `string`
      - type: `string`
- responses:
  - `200`: Incident status updated
    - `application/json`:
      - type: `object (12 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `monitor_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `resolved_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `severity` *required*: `string`
        - type: `string`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Incident not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/incidents/{incident_id}/updates`

- operationId: `get_incident_updates`
- summary: List the updates posted against one incident.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `incident_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Incident updates
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Incident not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/cancel`

- operationId: `knowledge_cancel_job`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `job_id` *required*: `string`
      - type: `string`
- responses:
  - `200`: The cancellation was accepted
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project or job

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/citations/verify`

- operationId: `knowledge_verify_citations`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `citations` *required*: `array<object (3 properties)>`
      - description: One to 50 citations, each quote 1 to 2,000 characters.
      - type: `array<object (3 properties)>`
    - `collection` *required*: `string`
      - description: The collection the chunks belong to.
      - type: `string`
    - `owner_ref`: `['string', 'null']`
      - description: The app owner the application vouches for.
      - type: `['string', 'null']`
    - `tenant`: `['string', 'null']`
      - description: The app tenant the application vouches for.
      - type: `['string', 'null']`
- responses:
  - `200`: One envelope per citation, in the order asked; a chunk that is missing, invisible or not serving is `unverifiable`
    - `application/json`:
      - type: `object (1 properties)`
      - `citations` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
  - `400`: Malformed request, or a value past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `503`: The rollout flag is off or a dependency is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/collections`

- operationId: `knowledge_list_collections`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The project's collections
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: A deployment token, or the member lacks knowledge.collections:read
  - `404`: Foreign organization or project, or the service is not enabled

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/collections`

- operationId: `knowledge_create_collection`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `collection` *required*: `string`
      - type: `string`
    - `environment` *required*: `string`
      - type: `string`
- responses:
  - `200`: The collection exists (created or already present)
    - `application/json`:
      - type: `any`
  - `400`: Malformed request
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project or environment
  - `409`: The name exists in another environment
  - `503`: The rollout flag is off or a dependency is unavailable

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/collections/{collection}/documents/{document_ref}`

- operationId: `knowledge_delete_collection_document`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `collection` (path) *required*: `string`
  - `document_ref` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The document is tombstoned and its vectors are being reconciled
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: A deployment token, or the member lacks knowledge.collections:manage
  - `404`: Foreign organization, project, collection or document
  - `503`: A dependency is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/collections/{collection}/promote`

- operationId: `knowledge_promote_collection`
- summary: Move the collection's alias to its candidate build, once every document is
ready in it. This call is the ADR-055 approval of a model change.
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `collection` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The candidate serves; the replaced build is retired
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: A deployment token, or the member lacks knowledge.collections:manage
  - `404`: Foreign organization, project or collection
  - `409`: No candidate, or documents not ready in it
  - `503`: A dependency is unavailable

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/documents/{document_ref}`

- operationId: `knowledge_delete_document`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `document_ref` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The document is tombstoned and its vectors are being reconciled
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or document
  - `503`: The rollout flag is off or a dependency is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/index`

- operationId: `knowledge_index`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `collection` *required*: `string`
      - type: `string`
    - `document_ref` *required*: `string`
      - type: `string`
    - `options` *required*: `object (9 properties)`
      - type: `object (9 properties)`
- responses:
  - `200`: The (possibly existing) indexing job
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, invalid metadata, or a value past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `413`: The request body is past its limit
  - `503`: The rollout flag is off or a dependency is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/index/inline`

- operationId: `knowledge_index_inline`
- summary: Index documents from the request, without a Blob object. All or none: one
bad item refuses the call and queues nothing. Each document keeps its own
durable job, as on `POST …/index`, and resubmitting the same text and
metadata answers the same job.
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `collection` *required*: `string`
      - type: `string`
    - `items` *required*: `array<object (6 properties)>`
      - description: One to 100 documents, within the 1 MiB body limit.
      - type: `array<object (6 properties)>`
- responses:
  - `200`: One job per item, in the items' order
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, invalid metadata, or a value past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `413`: The request body is past its limit
  - `503`: The rollout flag is off or a dependency is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/jobs/{job_id}`

- operationId: `knowledge_job_status`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `job_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The job state and progress
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project or job

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/passages`

- operationId: `knowledge_read_passages`
- summary: Read chunks' whole text by id, under the same access as search. An id the
caller may not read is left out of the answer, not refused, so the answer
says nothing about what exists.
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `chunk_ids` *required*: `array<string>`
      - description: One to 20 chunk ids.
      - type: `array<string>`
    - `collection` *required*: `string`
      - description: The collection the chunks belong to.
      - type: `string`
    - `owner_ref`: `['string', 'null']`
      - description: The app owner the application vouches for.
      - type: `['string', 'null']`
    - `tenant`: `['string', 'null']`
      - description: The app tenant the application vouches for.
      - type: `['string', 'null']`
- responses:
  - `200`: The readable passages, in the order asked
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, or a value past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `413`: The request body is past its limit
  - `503`: The rollout flag is off or a dependency is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/readiness`

- operationId: `knowledge_readiness`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The toolset readiness snapshot
    - `application/json`:
      - type: `any`
  - `401`: Unauthenticated, or the delegation assertion was not accepted
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization or project, or the service is not enabled

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/search`

- operationId: `knowledge_search`
- summary: The managed tool's read operation (`conusai.knowledge.search`): a read
tool replays a `GET`. Applications use the `POST` form, which keeps the
query text out of URLs.
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `collection` (query) *required*: `string`
  - `query` (query) *required*: `string`
  - `limit` (query): `integer`
  - `tenant` (query): `string`
  - `owner_ref` (query): `string`
  - `filter` (query): `string`
  - `rerank` (query): `boolean`
  - `rerank_candidates` (query): `integer`
  - `max_per_document` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cited, access-filtered results
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, or a filter past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `503`: The rollout flag is off or a dependency is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/knowledge/search`

- operationId: `knowledge_search_documents`
- tags: `Knowledge v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (9 properties)`
    - `collection` *required*: `string`
      - description: The collection to search.
      - type: `string`
    - `filter`: `object (1 properties) | null`
      - type: `object (1 properties) | null`
    - `limit`: `['integer', 'null']`
      - description: At most this many results (1–100, default 10; the plan may lower it).
      - type: `['integer', 'null']`
    - `max_per_document`: `['integer', 'null']`
      - description: Most hits of one document, 1 to 20 (default 3).
      - type: `['integer', 'null']`
    - `owner_ref`: `['string', 'null']`
      - description: The app owner the application vouches for.
      - type: `['string', 'null']`
    - `query` *required*: `string`
      - description: The query text.
      - type: `string`
    - `rerank`: `['boolean', 'null']`
      - description: Score the candidates with the local cross-encoder (default `true`).
      - type: `['boolean', 'null']`
    - `rerank_candidates`: `['integer', 'null']`
      - description: Fused candidates to rerank, 10 to 100 and at least `limit` (default 30).
      - type: `['integer', 'null']`
    - `tenant`: `['string', 'null']`
      - description: The app tenant the application vouches for.
      - type: `['string', 'null']`
- responses:
  - `200`: Cited, access-filtered results
    - `application/json`:
      - type: `any`
  - `400`: Malformed request, or a filter past its limit
  - `401`: Unauthenticated
  - `403`: Not a deployment token, or the token lacks knowledge.collections:use
  - `404`: Foreign organization, project, collection or environment
  - `413`: The request body is past its limit
  - `503`: The rollout flag is off or a dependency is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/del`

- operationId: `kv_del`
- summary: Delete one or more keys, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `keys` *required*: `array<string>`
      - description: The key(s) to delete
      - type: `array<string>`
- responses:
  - `200`: Keys deleted
    - `application/json`:
      - type: `object (1 properties)`
      - `deleted` *required*: `integer`
        - description: Number of keys deleted
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/expire`

- operationId: `kv_expire`
- summary: Set expiration on a key, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `key` *required*: `string`
      - description: The key to set expiration on
      - type: `string`
    - `seconds` *required*: `integer`
      - description: Expiration time in seconds
      - type: `integer`
- responses:
  - `200`: Expiration set
    - `application/json`:
      - type: `object (1 properties)`
      - `success` *required*: `boolean`
        - description: True if expiration was set, false if key doesn't exist
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/get`

- operationId: `kv_get`
- summary: Get a value by key, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `key` *required*: `string`
      - description: The key to retrieve
      - type: `string`
- responses:
  - `200`: Value retrieved
    - `application/json`:
      - type: `object (1 properties)`
      - `value`: `any`
        - description: The value, or null if not found
        - type: `any`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/incr`

- operationId: `kv_incr`
- summary: Increment a numeric value, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `amount`: `['integer', 'null']`
      - description: Amount to increment by (default: 1)
      - type: `['integer', 'null']`
    - `key` *required*: `string`
      - description: The key to increment
      - type: `string`
- responses:
  - `200`: Value incremented
    - `application/json`:
      - type: `object (1 properties)`
      - `value` *required*: `integer`
        - description: New value after increment
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/keys`

- operationId: `kv_keys`
- summary: List keys matching a pattern, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `pattern` *required*: `string`
      - description: Pattern to match (supports * and ? wildcards)
      - type: `string`
- responses:
  - `200`: Keys retrieved
    - `application/json`:
      - type: `object (1 properties)`
      - `keys` *required*: `array<string>`
        - description: List of matching keys
        - type: `array<string>`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/set`

- operationId: `kv_set`
- summary: Set a value, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `ex`: `['integer', 'null']`
      - description: Expire in seconds
      - type: `['integer', 'null']`
    - `key` *required*: `string`
      - description: The key to set
      - type: `string`
    - `nx`: `boolean`
      - description: Only set if key does not exist
      - type: `boolean`
    - `px`: `['integer', 'null']`
      - description: Expire in milliseconds
      - type: `['integer', 'null']`
    - `value` *required*: `any`
      - description: The value to store (can be any JSON value)
      - type: `any`
    - `xx`: `boolean`
      - description: Only set if key exists
      - type: `boolean`
- responses:
  - `200`: Value set
    - `application/json`:
      - type: `object (1 properties)`
      - `result` *required*: `string`
        - description: Always "OK" on success
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient organization permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/kv/ttl`

- operationId: `kv_ttl`
- summary: Get time-to-live for a key, in a path-scoped project.
- tags: `KV Store v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `key` *required*: `string`
      - description: The key to check TTL for
      - type: `string`
- responses:
  - `200`: TTL retrieved
    - `application/json`:
      - type: `object (1 properties)`
      - `ttl` *required*: `integer`
        - description: TTL in seconds, -1 if no expiration, -2 if key doesn't exist
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/logs`

- operationId: `purge_project_logs`
- tags: `Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `before` *required*: `string`
      - description: Delete all logs before this timestamp (ISO 8601)
      - type: `string`
- responses:
  - `200`: Purge completed
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/logs/context`

- operationId: `get_log_context`
- tags: `Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `chunk_id` (query) *required*: `string`
  - `line_offset` (query) *required*: `integer`
  - `lines` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Context lines
    - `application/json`:
      - type: `object (2 properties)`
      - `lines` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `target_index` *required*: `integer`
        - type: `integer`
  - `400`: Invalid parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Chunk not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/logs/search`

- operationId: `search_logs`
- tags: `Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `container_ids`: `array<string>`
      - type: `array<string>`
    - `context_lines`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `cursor`: `['string', 'null']`
      - type: `['string', 'null']`
    - `deploy_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `end_time`: `['string', 'null']`
      - type: `['string', 'null']`
    - `envs`: `array<string>`
      - type: `array<string>`
    - `levels`: `array<string>`
      - type: `array<string>`
    - `node_ids`: `array<integer>`
      - type: `array<integer>`
    - `page_size`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `services`: `array<string>`
      - type: `array<string>`
    - `start_time`: `['string', 'null']`
      - type: `['string', 'null']`
    - `text`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Search results
    - `application/json`:
      - type: `object (5 properties)`
      - `available_sources`: `array<object (4 properties)>`
        - description: Distinct containers/nodes/services available in the queried scope, for
        - type: `array<object (4 properties)>`
      - `lines` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
      - `search_mode` *required*: `string`
        - description: Search execution mode
        - type: `string`
      - `total_scanned` *required*: `integer`
        - type: `integer`
  - `400`: Invalid search parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/logs/tail`

- operationId: `tail_logs`
- tags: `Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `service` (query) *required*: `string`
  - `env` (query) *required*: `string`
  - `levels` (query) *required*: `array<string>`
  - `text` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: SSE stream of log lines
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/mcp-servers`

- operationId: `list_mcps`
- summary: List a project's MCP server definitions.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: MCP server definitions for the project
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/mcp-servers`

- operationId: `create_mcp`
- summary: Create an MCP server definition in a project.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `config` *required*: `object`
      - type: `object`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
- responses:
  - `201`: MCP server created
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: MCP server already exists

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/mcp-servers/{slug}`

- operationId: `get_mcp`
- summary: Get one MCP server definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: MCP server definition
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or MCP server not found in this workspace

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/mcp-servers/{slug}`

- operationId: `update_mcp`
- summary: Update an MCP server definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `config` *required*: `object`
      - type: `object`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: MCP server updated
    - `application/json`:
      - type: `object (8 properties)`
      - `config` *required*: `object`
        - type: `object`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or MCP server not found in this workspace

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/mcp-servers/{slug}`

- operationId: `delete_mcp`
- summary: Delete an MCP server definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: MCP server deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or MCP server not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors`

- operationId: `list_monitors`
- summary: List the monitors of one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Monitors in the project
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors`

- operationId: `create_monitor`
- summary: Create a monitor in one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `check_interval_seconds`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `check_path`: `['string', 'null']`
      - type: `['string', 'null']`
    - `environment_id` *required*: `integer`
      - type: `integer`
    - `monitor_type` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
- responses:
  - `201`: Monitor created
    - `application/json`:
      - type: `object (11 properties)`
      - `check_interval_seconds` *required*: `integer`
        - type: `integer`
      - `check_path`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `monitor_type` *required*: `string`
        - type: `string`
      - `monitor_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors/{monitor_id}`

- operationId: `get_monitor`
- summary: Read one monitor of one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `monitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Monitor details
    - `application/json`:
      - type: `object (11 properties)`
      - `check_interval_seconds` *required*: `integer`
        - type: `integer`
      - `check_path`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `is_active` *required*: `boolean`
        - type: `boolean`
      - `monitor_type` *required*: `string`
        - type: `string`
      - `monitor_url` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Monitor not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors/{monitor_id}`

- operationId: `delete_monitor`
- summary: Delete one monitor of one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `monitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Monitor deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Monitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors/{monitor_id}/bucketed`

- operationId: `get_bucketed_status`
- summary: Bucketed status series for one monitor.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `monitor_id` (path) *required*: `integer`
  - `interval` (query): `string`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Bucketed status data
    - `application/json`:
      - type: `object (3 properties)`
      - `buckets` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
      - `interval` *required*: `string`
        - type: `string`
      - `monitor_id` *required*: `integer`
        - type: `integer`
  - `400`: Invalid parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Monitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors/{monitor_id}/current-status`

- operationId: `get_current_monitor_status`
- summary: Current status and uptime metrics for one monitor.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `monitor_id` (path) *required*: `integer`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Current status
    - `application/json`:
      - type: `object (5 properties)`
      - `avg_response_time_ms`: `['number', 'null']`
        - type: `['number', 'null']`
      - `current_status` *required*: `string`
        - type: `string`
      - `last_check_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `monitor_id` *required*: `integer`
        - type: `integer`
      - `uptime_percentage` *required*: `number`
        - type: `number`
  - `400`: Invalid time parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Monitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/monitors/{monitor_id}/uptime`

- operationId: `get_uptime_history`
- summary: Uptime history for one monitor.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `monitor_id` (path) *required*: `integer`
  - `start_time` (query) *required*: `string`
  - `end_time` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Uptime history
    - `application/json`:
      - type: `object (2 properties)`
      - `monitor_id` *required*: `integer`
        - type: `integer`
      - `uptime_data` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
  - `400`: Invalid time parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Monitor not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/analyses`

- operationId: `start_obs_analysis`
- summary: Start an analysis run for an issue or a friction report (observe-sdk
P6.2). The run is created immediately and executes in the background;
poll `GET obs/analyses/{run_id}` for progress.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `friction_report_id`: `['integer', 'null']`
      - description: Friction report to analyze (observe-sdk P6.2): the same run shape
      - type: `['integer', 'null']`
    - `issue_id`: `['integer', 'null']`
      - description: Issue (error group) to analyze.
      - type: `['integer', 'null']`
    - `stop_at`: `string | null`
      - type: `string | null`
    - `user_context`: `['string', 'null']`
      - description: Free-text notes for the model, included verbatim in the prompt.
      - type: `['string', 'null']`
- responses:
  - `202`: Analysis started
    - `application/json`:
      - type: `object (8 properties)`
      - `analysis`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `phase`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `run_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `stop_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trace_id`: `['string', 'null']`
        - description: The run's trace id — the agent's OTLP telemetry lands on this trace
        - type: `['string', 'null']`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Missing obs:write (API key) or write standing (session)
  - `404`: Friction report not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/analyses/{run_id}`

- operationId: `get_obs_analysis`
- summary: Read one analysis run.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `run_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Analysis run
    - `application/json`:
      - type: `object (8 properties)`
      - `analysis`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `phase`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `run_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `stop_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `trace_id`: `['string', 'null']`
        - description: The run's trace id — the agent's OTLP telemetry lands on this trace
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `404`: Run not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/annotations`

- operationId: `list_obs_annotations`
- summary: List the project's timeline markers, oldest first, with keyset
pagination over `(ts, id)`.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `from` (query): `['string', 'null']`
  - `to` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `cursor` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Page of annotations
    - `application/json`:
      - type: `object (3 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `422`: Invalid cursor
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/annotations`

- operationId: `create_obs_annotation`
- summary: Pin a marker to the project's timeline. Markers are stored in
`obs_annotations` and surfaced by the markers route once it exists; they
are never ingested as Observe events.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `kind` *required*: `string`
      - description: Marker kinds (C7). Annotations are timeline markers only — they never
      - type: `string`
    - `text` *required*: `string`
      - type: `string`
    - `ts` *required*: `string`
      - description: The moment the marker refers to.
      - type: `string`
- responses:
  - `201`: Annotation created
    - `application/json`:
      - type: `object (6 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `created_by_user_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - type: `string`
      - `text` *required*: `string`
        - type: `string`
      - `ts` *required*: `string`
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Missing obs:write (API key) or write standing (session)
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/changes`

- operationId: `list_obs_changes`
- summary: The changes feed: deployments of this project plus — only when the caller
holds `audit:read` (D20/C7) — the project's audit rows, merged
time-descending.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `from` (query): `['string', 'null']`
  - `to` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `offset` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Page of changes
    - `application/json`:
      - type: `object (2 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/friction`

- operationId: `list_obs_friction`
- summary: The nightly friction reports (observe-sdk P6.2, C7): the read the
console Friction page and the `list_obs_friction` tool list with.
Project read standing only — friction findings carry no secrets.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `from` (query): `['string', 'null']`
  - `to` (query): `['string', 'null']`
  - `route` (query): `['string', 'null']`
  - `min_users` (query): `['integer', 'null']`
  - `limit` (query): `['integer', 'null']`
  - `offset` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Page of friction reports
    - `application/json`:
      - type: `object (2 properties)`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `items` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/obs/issues/{issue_id}/evidence`

- operationId: `get_obs_evidence`
- summary: The evidence bundle for an issue (observe-sdk P5.3, C6/D18/D19): every
signal the agent would research, capped, sanitized and budgeted. Treat it as
untrusted data. `format=prompt` returns the rendered D19 prompt (preamble +
`<evidence … untrusted="true">` fences); `format=json` returns the bundle
with that preamble and an `untrusted` label. A missing issue reads as 404,
like every project-scoped read.
- tags: `Obs`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `issue_id` (path) *required*: `integer`
  - `format` (query): `['string', 'null']`
  - `event_id` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Rendered prompt (prompt) or labelled evidence bundle (json)
    - `application/json`:
      - type: `object`
  - `400`: Unknown format
  - `401`: Unauthorized
  - `404`: Issue not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/observe/events`

- operationId: `observability_list_events`
- summary: List observability events for one path-scoped project.
- tags: `Observability v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `kinds` (query): `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `deployment_id` (query): `integer`
  - `environment_id` (query): `integer`
  - `search` (query): `string`
  - `limit` (query): `integer`
  - `hide_bots` (query): `boolean`
  - `session_id` (query): `string`
  - `trace_id` (query): `string`
  - `request_id` (query): `string`
  - `cursor` (query): `string`
  - `response_format` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Merged event page
    - `application/json`:
      - type: `object (4 properties)`
      - `applied_kinds` *required*: `array<string>`
        - description: Echo of the kinds filter actually applied (server-resolved). Useful
        - type: `array<string>`
      - `events` *required*: `array<any | any | any | any | any>`
        - type: `array<any | any | any | any | any>`
      - `has_more` *required*: `boolean`
        - type: `boolean`
      - `next_cursor`: `['string', 'null']`
        - description: Pass back as `cursor` for the next page; `null` on the last page.
        - type: `['string', 'null']`
  - `400`: Invalid filter
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/observe/events/{kind}/{event_id}/full`

- operationId: `observability_full_event`
- summary: Fetch the un-truncated form of one observability event in a path-scoped
project.
- tags: `Observability v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `kind` (path) *required*: `string`
  - `event_id` (path) *required*: `string`
  - `ts` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Full row
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Event not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts`

- operationId: `list_alerts`
- summary: List one project's metric alert rules.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Alert rules in the project
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (24 properties)>`
        - type: `array<object (24 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts`

- operationId: `create_alert`
- summary: Create a metric alert rule in one project.
- description: The body's `project_id` is discarded in favour of the path.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (14 properties)`
    - `aggregation` *required*: `string`
      - description: One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`.
      - type: `string`
    - `detection_config` *required*: `any | any | any | any | any`
      - description: The typed detector definition stored (as jsonb) in
      - type: `any | any | any | any | any`
    - `dynamic_alerts`: `boolean`
      - description: When true (and `group_by` is set) fire one independent alarm per breaching
      - type: `boolean`
    - `enabled` *required*: `boolean`
      - type: `boolean`
    - `for_duration_secs` *required*: `integer`
      - type: `integer`
    - `group_by`: `array<string>`
      - description: Label keys to break the metric down by, e.g. `["endpoint","region"]`. Empty
      - type: `array<string>`
    - `grouped_notification_threshold`: `integer`
      - description: When more than this many series transition to firing in the same tick, only
      - type: `integer`
    - `label_filters`: `array<array<any>>`
      - description: AND-combined label equality filters: `[["key","value"],…]`. Empty = no
      - type: `array<array<any>>`
    - `max_series`: `integer`
      - description: Cardinality cap for dynamic alerting: at most this many series (top by
      - type: `integer`
    - `metric_name` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `severity` *required*: `string`
      - description: One of `info|warning|critical`.
      - type: `string`
    - `window_secs` *required*: `integer`
      - type: `integer`
- responses:
  - `201`: Alert rule created
    - `application/json`:
      - type: `object (24 properties)`
      - `aggregation` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `detection_config` *required*: `any | any | any | any | any`
        - description: The typed detector definition stored (as jsonb) in
        - type: `any | any | any | any | any`
      - `detection_kind` *required*: `string`
        - description: Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`.
        - type: `string`
      - `dynamic_alerts` *required*: `boolean`
        - description: Whether per-series ("dynamic") alerting is enabled for this rule.
        - type: `boolean`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `firing_series`: `array<object (3 properties)>`
        - description: Currently-firing series for a dynamic rule, snapshotted from the evaluator's
        - type: `array<object (3 properties)>`
      - `for_duration_secs` *required*: `integer`
        - type: `integer`
      - `group_by` *required*: `array<string>`
        - description: Label keys the rule breaks the metric down by. Empty = one aggregate stream.
        - type: `array<string>`
      - `grouped_notification_threshold` *required*: `integer`
        - description: Notification-grouping threshold: when more than this many series fire in the
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `label_filters` *required*: `array<array<any>>`
        - description: AND-combined label equality filters applied when evaluating this rule.
        - type: `array<array<any>>`
      - `last_dropped_series_count` *required*: `integer`
        - description: Number of series dropped by the cardinality cap on the latest dynamic tick
        - type: `integer`
      - `last_evaluated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_state` *required*: `string`
        - description: One of `ok|firing|unknown`.
        - type: `string`
      - `last_value`: `['number', 'null']`
        - type: `['number', 'null']`
      - `max_series` *required*: `integer`
        - description: Cardinality cap for dynamic alerting (1–100).
        - type: `integer`
      - `metric_name` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `series_states` *required*: `object`
        - description: Full per-series state snapshot persisted after the latest dynamic-rule tick,
        - type: `object`
      - `severity` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `window_secs` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts/preview`

- operationId: `preview_alert`
- summary: Backtest an anomaly detector against one project's history.
- description: The body's `project_id` is discarded in favour of the path.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `aggregation` *required*: `string`
      - description: One of `avg|sum|min|max|count|rate|p50|p90|p95|p99`.
      - type: `string`
    - `detection_config` *required*: `any | any | any | any | any`
      - description: The typed detector definition stored (as jsonb) in
      - type: `any | any | any | any | any`
    - `end_time`: `['string', 'null']`
      - description: RFC 3339; defaults to now.
      - type: `['string', 'null']`
    - `metric_name` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `start_time`: `['string', 'null']`
      - description: RFC 3339; defaults to 7 days before `end_time`.
      - type: `['string', 'null']`
    - `window_secs` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Backtest result
    - `application/json`:
      - type: `object (4 properties)`
      - `baseline_samples` *required*: `integer`
        - description: Baseline sample count (drives the `sufficient` flag).
        - type: `integer`
      - `breach_count` *required*: `integer`
        - description: How many points in the range would have fired.
        - type: `integer`
      - `points` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `sufficient` *required*: `boolean`
        - description: Whether the baseline had enough history for a trustworthy band.
        - type: `boolean`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts/{id}`

- operationId: `get_alert`
- summary: Read one metric alert rule of one project.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Alert rule details
    - `application/json`:
      - type: `object (24 properties)`
      - `aggregation` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `detection_config` *required*: `any | any | any | any | any`
        - description: The typed detector definition stored (as jsonb) in
        - type: `any | any | any | any | any`
      - `detection_kind` *required*: `string`
        - description: Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`.
        - type: `string`
      - `dynamic_alerts` *required*: `boolean`
        - description: Whether per-series ("dynamic") alerting is enabled for this rule.
        - type: `boolean`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `firing_series`: `array<object (3 properties)>`
        - description: Currently-firing series for a dynamic rule, snapshotted from the evaluator's
        - type: `array<object (3 properties)>`
      - `for_duration_secs` *required*: `integer`
        - type: `integer`
      - `group_by` *required*: `array<string>`
        - description: Label keys the rule breaks the metric down by. Empty = one aggregate stream.
        - type: `array<string>`
      - `grouped_notification_threshold` *required*: `integer`
        - description: Notification-grouping threshold: when more than this many series fire in the
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `label_filters` *required*: `array<array<any>>`
        - description: AND-combined label equality filters applied when evaluating this rule.
        - type: `array<array<any>>`
      - `last_dropped_series_count` *required*: `integer`
        - description: Number of series dropped by the cardinality cap on the latest dynamic tick
        - type: `integer`
      - `last_evaluated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_state` *required*: `string`
        - description: One of `ok|firing|unknown`.
        - type: `string`
      - `last_value`: `['number', 'null']`
        - type: `['number', 'null']`
      - `max_series` *required*: `integer`
        - description: Cardinality cap for dynamic alerting (1–100).
        - type: `integer`
      - `metric_name` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `series_states` *required*: `object`
        - description: Full per-series state snapshot persisted after the latest dynamic-rule tick,
        - type: `object`
      - `severity` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `window_secs` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Alert rule not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts/{id}`

- operationId: `update_alert`
- summary: Update one metric alert rule of one project.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (13 properties)`
    - `aggregation`: `['string', 'null']`
      - type: `['string', 'null']`
    - `detection_config`: `any | any | any | any | any | null`
      - type: `any | any | any | any | any | null`
    - `dynamic_alerts`: `['boolean', 'null']`
      - description: Toggles per-series ("dynamic") alerting (absent = leave unchanged).
      - type: `['boolean', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `for_duration_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `group_by`: `['array', 'null']`
      - description: Replaces the `group_by` keys wholesale when present (absent = leave unchanged).
      - type: `['array', 'null']`
    - `grouped_notification_threshold`: `['integer', 'null']`
      - description: Updates the notification-grouping threshold (absent = leave unchanged).
      - type: `['integer', 'null']`
    - `label_filters`: `['array', 'null']`
      - description: Replaces the label filters wholesale when present (absent = leave unchanged).
      - type: `['array', 'null']`
    - `max_series`: `['integer', 'null']`
      - description: Updates the dynamic-alerting cardinality cap (absent = leave unchanged).
      - type: `['integer', 'null']`
    - `metric_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `severity`: `['string', 'null']`
      - type: `['string', 'null']`
    - `window_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `200`: Alert rule updated
    - `application/json`:
      - type: `object (24 properties)`
      - `aggregation` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `detection_config` *required*: `any | any | any | any | any`
        - description: The typed detector definition stored (as jsonb) in
        - type: `any | any | any | any | any`
      - `detection_kind` *required*: `string`
        - description: Coarse detector discriminator: `static|anomaly|forecast|outlier|auto_watch`.
        - type: `string`
      - `dynamic_alerts` *required*: `boolean`
        - description: Whether per-series ("dynamic") alerting is enabled for this rule.
        - type: `boolean`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `firing_series`: `array<object (3 properties)>`
        - description: Currently-firing series for a dynamic rule, snapshotted from the evaluator's
        - type: `array<object (3 properties)>`
      - `for_duration_secs` *required*: `integer`
        - type: `integer`
      - `group_by` *required*: `array<string>`
        - description: Label keys the rule breaks the metric down by. Empty = one aggregate stream.
        - type: `array<string>`
      - `grouped_notification_threshold` *required*: `integer`
        - description: Notification-grouping threshold: when more than this many series fire in the
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `label_filters` *required*: `array<array<any>>`
        - description: AND-combined label equality filters applied when evaluating this rule.
        - type: `array<array<any>>`
      - `last_dropped_series_count` *required*: `integer`
        - description: Number of series dropped by the cardinality cap on the latest dynamic tick
        - type: `integer`
      - `last_evaluated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_state` *required*: `string`
        - description: One of `ok|firing|unknown`.
        - type: `string`
      - `last_value`: `['number', 'null']`
        - type: `['number', 'null']`
      - `max_series` *required*: `integer`
        - description: Cardinality cap for dynamic alerting (1–100).
        - type: `integer`
      - `metric_name` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `series_states` *required*: `object`
        - description: Full per-series state snapshot persisted after the latest dynamic-rule tick,
        - type: `object`
      - `severity` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `window_secs` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Alert rule not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/alerts/{id}`

- operationId: `delete_alert`
- summary: Delete one metric alert rule of one project.
- tags: `Metric Alerts v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Alert rule deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Alert rule not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/dashboards`

- operationId: `list_dashboards`
- summary: List one project's saved metric dashboards.
- tags: `Dashboards v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Dashboards in the project
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/dashboards`

- operationId: `create_dashboard`
- summary: Create a dashboard in one project.
- description: The body's `project_id` is discarded in favour of the path — see the module
docs.
- tags: `Dashboards v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `layout` *required*: `object (1 properties)`
      - description: The typed layout persisted (as JSONB) in `metric_dashboards.layout`.
      - type: `object (1 properties)`
    - `name` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
- responses:
  - `201`: Dashboard created
    - `application/json`:
      - type: `object (6 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `layout` *required*: `object (1 properties)`
        - description: The typed layout persisted (as JSONB) in `metric_dashboards.layout`.
        - type: `object (1 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/dashboards/{id}`

- operationId: `get_dashboard`
- summary: Read one dashboard of one project.
- tags: `Dashboards v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Dashboard details
    - `application/json`:
      - type: `object (6 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `layout` *required*: `object (1 properties)`
        - description: The typed layout persisted (as JSONB) in `metric_dashboards.layout`.
        - type: `object (1 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Dashboard not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/dashboards/{id}`

- operationId: `update_dashboard`
- summary: Update one dashboard of one project.
- tags: `Dashboards v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `layout`: `object (1 properties) | null`
      - type: `object (1 properties) | null`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Dashboard updated
    - `application/json`:
      - type: `object (6 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `layout` *required*: `object (1 properties)`
        - description: The typed layout persisted (as JSONB) in `metric_dashboards.layout`.
        - type: `object (1 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Validation error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Dashboard not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/dashboards/{id}`

- operationId: `delete_dashboard`
- summary: Delete one dashboard of one project.
- tags: `Dashboards v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Dashboard deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Insufficient permissions
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Dashboard not found in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/log-services`

- operationId: `list_project_log_services`
- tags: `Telemetry v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<string>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/logs`

- operationId: `query_project_logs`
- tags: `Telemetry v1`
- parameters:
  - `severity` (query): `string`
  - `service_name` (query): `string`
  - `search` (query): `string`
  - `trace_id` (query): `string`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/trace-summaries`

- operationId: `query_project_trace_summaries`
- tags: `Telemetry v1`
- parameters:
  - `trace_id` (query): `string`
  - `service_name` (query): `string`
  - `status` (query): `string`
  - `min_duration_ms` (query): `number`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `attributes` (query): `string`
  - `name_pattern` (query): `string`
  - `sort_by` (query): `string`
  - `sort_order` (query): `string`
  - `include_total` (query): `boolean`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `data` *required*: `array<object (10 properties)>`
        - type: `array<object (10 properties)>`
      - `total`: `['integer', 'null']`
        - description: Total traces matching the filters, ignoring pagination. Omitted when
        - type: `['integer', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/traces`

- operationId: `query_project_traces`
- tags: `Telemetry v1`
- parameters:
  - `trace_id` (query): `string`
  - `service_name` (query): `string`
  - `status` (query): `string`
  - `min_duration_ms` (query): `number`
  - `start_time` (query): `string`
  - `end_time` (query): `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `attributes` (query): `string`
  - `name_pattern` (query): `string`
  - `sort_by` (query): `string`
  - `sort_order` (query): `string`
  - `include_total` (query): `boolean`
  - `limit` (query): `integer`
  - `offset` (query): `integer`
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/otel/traces/{trace_id}`

- operationId: `get_project_trace`
- tags: `Telemetry v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `trace_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (2 properties)`
      - `count` *required*: `integer`
        - type: `integer`
      - `data` *required*: `array<object (15 properties)>`
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Forbidden
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not Found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/performance/has-metrics`

- operationId: `has_performance_metrics`
- summary: Check whether performance metrics exist for one path-scoped project.
- tags: `Performance v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Has-metrics check result
    - `application/json`:
      - type: `object (1 properties)`
      - `has_metrics` *required*: `boolean`
        - type: `boolean`
  - `401`: Authentication required
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/performance/metrics`

- operationId: `get_performance_metrics`
- summary: Get performance metrics for one path-scoped project.
- tags: `Performance v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `device_type` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Performance metrics
  - `400`: Invalid request
  - `401`: Authentication required
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/performance/metrics-over-time`

- operationId: `get_metrics_over_time`
- summary: Get performance metrics over time for one path-scoped project.
- tags: `Performance v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `device_type` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Metrics over time
  - `400`: Invalid request
  - `401`: Authentication required
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/performance/page-metrics`

- operationId: `get_grouped_page_metrics`
- summary: Get grouped page metrics for one path-scoped project.
- tags: `Performance v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `group_by` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Grouped page metrics
  - `400`: Invalid request
  - `401`: Authentication required
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/privacy/requests`

- operationId: `list_requests`
- summary: The project's privacy requests, newest first.
- tags: `Privacy`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Requests
    - `application/json`:
      - type: `object (1 properties)`
      - `requests` *required*: `array<object (13 properties)>`
        - type: `array<object (13 properties)>`
  - `403`: Not an organization owner or admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/privacy/requests`

- operationId: `create_request`
- summary: Ask for one person's erasure or export.
- description: Answers 202 with a new job, or 200 with the open job for the same kind and
person (a repeated request is idempotent while one is pending or running).
- tags: `Privacy`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `kind` *required*: `string`
      - description: What a request does.
      - type: `string`
    - `subject` *required*: `object (2 properties)`
      - description: Exactly one key names the person.
      - type: `object (2 properties)`
- responses:
  - `200`: An open request for the same kind and person
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `202`: Request created
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `400`: Not exactly one subject key, or an invalid one
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Not an organization owner or admin, or a refused credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Project not found
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/privacy/requests/{request_id}`

- operationId: `get_request`
- summary: One request: its status and per-store results.
- tags: `Privacy`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The request
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `404`: No such request in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/privacy/requests/{request_id}/export`

- operationId: `download_export`
- summary: The export document of a completed export request: JSON with one
document per store (`format: conusai.privacy.export/v1`). Kept for seven
days after completion.
- tags: `Privacy`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The export document
    - `application/json`:
      - type: `object (7 properties)`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `format` *required*: `string`
        - description: Always `conusai.privacy.export/v1`.
        - type: `string`
      - `generated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `request_id` *required*: `string`
        - type: `string`
      - `stores` *required*: `object`
        - description: Each store's export document, by store name.
        - type: `object`
      - `subject` *required*: `object (1 properties)`
        - description: The person an export is about: only the kind of key, never its value.
        - type: `object (1 properties)`
  - `404`: No such request in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Not ready, failed, expired, or an erasure
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-files`

- operationId: `list_source_files`
- summary: List the uploaded source files of one release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of source files
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-files`

- operationId: `upload_source_file`
- summary: Upload a raw source file for a release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: Source file uploaded
  - `400`: Missing fields
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Source context disabled for project
  - `413`: Source file too large

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-files`

- operationId: `delete_release_source_files`
- summary: Delete every uploaded source file of one release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Source files deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-maps`

- operationId: `list_source_maps`
- summary: List the source maps of one release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of source maps
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-maps`

- operationId: `upload_source_map`
- summary: Upload a source map for a release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: Source map uploaded
  - `400`: Invalid source map or missing fields
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `413`: Source map too large

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/releases/{release}/source-maps`

- operationId: `delete_release_source_maps`
- summary: Delete every source map of one release of one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `release` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Source maps deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/compare`

- operationId: `compare_records`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `allowAi` *required*: `boolean`
      - type: `boolean`
    - `items` *required*: `array<object (4 properties)>`
      - type: `array<object (4 properties)>`
    - `profile` *required*: `object (2 properties)`
      - type: `object (2 properties)`
    - `recipeHash` *required*: `string`
      - type: `string`
    - `requestId` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Deterministic suggestions or abstention for each supplied item
    - `application/json`:
      - type: `object (3 properties)`
      - `requestId` *required*: `string`
        - type: `string`
      - `results` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
      - `schemaVersion` *required*: `integer`
        - type: `integer`
  - `400`: Strict DTO, decimal, uniqueness or evidence validation failed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization plan lacks ai_tools
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:compare, insufficient scope, or feature disabled
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The organization, workspace or project is not visible
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Encoded request, item, candidate or fact bound exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Unsupported comparison profile
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Request concurrency allowance exhausted
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Policy admission unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `504`: Comparison deadline exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans`

- operationId: `propose_resolution_plan`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (11 properties)`
    - `adapterVersion` *required*: `string`
      - type: `string`
    - `batchId` *required*: `string`
      - type: `string`
    - `expiresAt` *required*: `string`
      - description: RFC 3339 timestamp, at most 168 hours ahead.
      - type: `string`
    - `operations` *required*: `array<object (5 properties)>`
      - type: `array<object (5 properties)>`
    - `policyVersion` *required*: `string`
      - type: `string`
    - `preconditions` *required*: `array<object (4 properties)>`
      - type: `array<object (4 properties)>`
    - `profileVersion` *required*: `string`
      - type: `string`
    - `recipeHash` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
    - `sourceSnapshotHashes` *required*: `array<string>`
      - type: `array<string>`
    - `submissionKey` *required*: `string`
      - type: `string`
- responses:
  - `200`: Identical resubmission under the same key; `replayed` is true
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `201`: Plan stored
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Plan validation failed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization plan lacks ai_tools
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:apply or resolution:merge, or a disabled flag
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The organization, workspace or project is not visible
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: IDEMPOTENCY_CONFLICT: the submission key was used with another payload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Plan bound exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `422`: Reserved or unsupported field target
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Policy or ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}`

- operationId: `get_resolution_plan`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The plan, its status, decision and application
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not visible in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}/apply`

- operationId: `claim_resolution_apply`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `idempotencyKey` *required*: `string`
      - type: `string`
    - `planHash` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Application claimed (or identically replayed); apply in the owning application, then report results
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Malformed claim
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:apply or merge authority, or a disabled flag
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not visible in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: APPROVAL_REQUIRED, PLAN_STALE, PLAN_CANCELLED, MERGE_CONFLICT, IDEMPOTENCY_CONFLICT, APPLY_IN_PROGRESS or ALREADY_APPLIED
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Policy or ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}/cancel`

- operationId: `cancel_resolution_plan`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `planHash` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Cancelled before any claim, or already cancelled
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Malformed cancel
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:apply
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not visible in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: PLAN_STALE, APPLY_IN_PROGRESS, ALREADY_APPLIED or PLAN_REJECTED
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}/decisions`

- operationId: `decide_resolution_plan`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `decision` *required*: `string`
      - type: `string`
    - `planHash` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Decision recorded or identically replayed
    - `application/json`:
      - type: `object (7 properties)`
      - `application` *required*: `object (5 properties) | null`
        - type: `object (5 properties) | null`
      - `createdAt` *required*: `string`
        - type: `string`
      - `decision` *required*: `object (6 properties) | null`
        - type: `object (6 properties) | null`
      - `plan` *required*: `object (14 properties)`
        - description: The immutable, server-built plan. `hash` is SHA-256 over the canonical
        - type: `object (14 properties)`
      - `proposedBy` *required*: `string`
        - type: `string`
      - `replayed` *required*: `boolean`
        - description: True when this response replays an earlier identical request.
        - type: `boolean`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Malformed decision
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: HUMAN_APPROVAL_REQUIRED, MERGE_PERMISSION_REQUIRED or missing resolution:decide
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not visible in this project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: PLAN_STALE, DECISION_CONFLICT or PLAN_CANCELLED
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Policy or ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}/results`

- operationId: `get_resolution_result`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The recorded report; re-authorized on every read
    - `application/json`:
      - type: `object (2 properties)`
      - `plan` *required*: `object (7 properties)`
        - type: `object (7 properties)`
      - `result` *required*: `object (6 properties)`
        - type: `object (6 properties)`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing resolution:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not visible, or no report recorded yet
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resolution/plans/{plan_id}/results`

- operationId: `record_resolution_result`
- tags: `Resolution v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `plan_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `complete` *required*: `boolean`
      - description: Every operation is accounted for (including failures); not "all
      - type: `boolean`
    - `outcomes` *required*: `array<object (4 properties) | object (3 properties) | object (3 properties) | object (3 properties) | object (4 properties) | object (4 properties)>`
      - type: `array<object (4 properties) | object (3 properties) | object (3 properties) | object (3 properties) | object (4 properties) | object (4 properties)>`
    - `planHash` *required*: `string`
      - type: `string`
    - `planId` *required*: `string`
      - type: `string`
    - `runId` *required*: `string`
      - type: `string`
    - `schemaVersion` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Complete report recorded with receipts and audit, or identically replayed
    - `application/json`:
      - type: `object (2 properties)`
      - `plan` *required*: `object (7 properties)`
        - type: `object (7 properties)`
      - `result` *required*: `object (6 properties)`
        - type: `object (6 properties)`
  - `400`: Report inconsistent with the plan
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthenticated
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: EXECUTOR_MISMATCH or missing resolution:apply
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Plan or run not visible
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: IDEMPOTENCY_CONFLICT: a different report was already recorded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Report bound exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: Ledger store unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/resource-ceiling`

- operationId: `get_project_resource_ceiling`
- summary: The CPU and memory ceiling of one container of this project (ADR-048).
- tags: `Environments`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The organisation's per-container ceiling
    - `application/json`:
      - type: `object (4 properties)`
      - `cpu_is_platform_default` *required*: `boolean`
        - description: `true` when the plan sets no CPU ceiling and this is the platform default.
        - type: `boolean`
      - `cpu_microcores` *required*: `integer`
        - description: Microcores (`1_000_000` = one core).
        - type: `integer`
      - `memory_is_platform_default` *required*: `boolean`
        - description: `true` when the plan sets no memory ceiling and this is the platform default.
        - type: `boolean`
      - `memory_mb` *required*: `integer`
        - description: MiB.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/events`

- operationId: `revenue_recent_events`
- summary: Recent ingested revenue events for one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (6 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations`

- operationId: `revenue_list_integrations`
- summary: List the revenue integrations of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (10 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations`

- operationId: `revenue_create_integration`
- summary: Create a revenue integration in one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `provider` *required*: `string`
      - description: Registered provider name, e.g. "stripe".
      - type: `string`
    - `signing_secret` *required*: `string`
      - description: Signing secret from the provider's dashboard.
      - type: `string`
- responses:
  - `201`: Created
    - `application/json`:
      - type: `object (10 properties)`
      - `config`: `any | any | null`
        - type: `any | any | null`
      - `created_at` *required*: `string`
        - type: `string`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_event_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `webhook_path` *required*: `string`
        - description: Relative path the UI can display and copy. The frontend builds
        - type: `string`
      - `webhook_path_token` *required*: `string`
        - description: Unguessable token embedded in the public webhook URL. The full
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Already connected

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}`

- operationId: `revenue_delete_integration`
- summary: Delete one revenue integration of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Integration deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}/config`

- operationId: `revenue_update_config`
- summary: Replace the typed provider config of one integration of one path-scoped
project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `config`: `any | any | null`
      - type: `any | any | null`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (10 properties)`
      - `config`: `any | any | null`
        - type: `any | any | null`
      - `created_at` *required*: `string`
        - type: `string`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_event_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `webhook_path` *required*: `string`
        - description: Relative path the UI can display and copy. The frontend builds
        - type: `string`
      - `webhook_path_token` *required*: `string`
        - description: Unguessable token embedded in the public webhook URL. The full
        - type: `string`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}/import/invoices`

- operationId: `revenue_import_invoices_csv`
- summary: Import an invoices CSV into one integration of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (6 properties)`
      - `errors` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `inserted` *required*: `integer`
        - type: `integer`
      - `rows_read` *required*: `integer`
        - type: `integer`
      - `skipped_invalid` *required*: `integer`
        - type: `integer`
      - `skipped_stale` *required*: `integer`
        - type: `integer`
      - `updated` *required*: `integer`
        - type: `integer`
  - `400`: Malformed CSV or wrong provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project
  - `413`: CSV too large

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}/import/subscriptions`

- operationId: `revenue_import_subscriptions_csv`
- summary: Import a subscriptions CSV into one integration of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (6 properties)`
      - `errors` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `inserted` *required*: `integer`
        - type: `integer`
      - `rows_read` *required*: `integer`
        - type: `integer`
      - `skipped_invalid` *required*: `integer`
        - type: `integer`
      - `skipped_stale` *required*: `integer`
        - type: `integer`
      - `updated` *required*: `integer`
        - type: `integer`
  - `400`: Malformed CSV or wrong provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project
  - `413`: CSV too large

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}/rotate-token`

- operationId: `revenue_rotate_token`
- summary: Rotate the webhook path token of one integration of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (10 properties)`
      - `config`: `any | any | null`
        - type: `any | any | null`
      - `created_at` *required*: `string`
        - type: `string`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_event_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `webhook_path` *required*: `string`
        - description: Relative path the UI can display and copy. The frontend builds
        - type: `string`
      - `webhook_path_token` *required*: `string`
        - description: Unguessable token embedded in the public webhook URL. The full
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/integrations/{integration_id}/update-secret`

- operationId: `revenue_update_secret`
- summary: Replace the signing secret of one integration of one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `integration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `signing_secret` *required*: `string`
      - description: New signing secret from the provider's dashboard. Encrypted at
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (10 properties)`
      - `config`: `any | any | null`
        - type: `any | any | null`
      - `created_at` *required*: `string`
        - type: `string`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_event_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `provider` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `webhook_path` *required*: `string`
        - description: Relative path the UI can display and copy. The frontend builds
        - type: `string`
      - `webhook_path_token` *required*: `string`
        - description: Unguessable token embedded in the public webhook URL. The full
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Integration not found in this project

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/metrics/customers`

- operationId: `revenue_metrics_customers`
- summary: New + churned customers per bucket, for one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `bucket` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/metrics/mrr`

- operationId: `revenue_metrics_mrr`
- summary: Bucketed MRR timeseries for one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `currency` (query): `string`
  - `from` (query): `string`
  - `to` (query): `string`
  - `bucket` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/revenue/metrics/summary`

- operationId: `revenue_metrics_summary`
- summary: MRR / ARR / churn / ARPU for one path-scoped project.
- tags: `Revenue v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `currency` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `active_customers` *required*: `integer`
        - type: `integer`
      - `active_subscriptions` *required*: `integer`
        - type: `integer`
      - `arpu_minor` *required*: `integer`
        - type: `integer`
      - `churned_last_30d` *required*: `integer`
        - type: `integer`
      - `currency` *required*: `string`
        - type: `string`
      - `current_arr_minor` *required*: `integer`
        - type: `integer`
      - `current_mrr_minor` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/secrets`

- operationId: `list_project_secrets`
- summary: List one project's file-mounted secrets.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Project secrets
    - `application/json`:
      - type: `array<object (7 properties)>`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/secrets`

- operationId: `create_project_secret`
- summary: Create a file-mounted secret in one project.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `environment_ids`: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - description: Include this secret in preview environments.
      - type: `boolean`
    - `key` *required*: `string`
      - description: Identifier for the secret. Becomes the filename at `/run/secrets/<KEY>`.
      - type: `string`
    - `value` *required*: `string`
      - description: Plaintext value, <= 1 MiB.
      - type: `string`
- responses:
  - `201`: Secret created
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/secrets/{secret_id}`

- operationId: `update_project_secret`
- summary: Update one file-mounted secret.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `secret_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `environment_ids`: `array<integer>`
      - type: `array<integer>`
    - `include_in_preview`: `boolean`
      - type: `boolean`
    - `value`: `['string', 'null']`
      - description: New plaintext value, <= 1 MiB. Omit to keep the existing value.
      - type: `['string', 'null']`
- responses:
  - `200`: Secret updated
    - `application/json`:
      - type: `object (7 properties)`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `environments` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_in_preview` *required*: `boolean`
        - type: `boolean`
      - `key` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `404`: Secret not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/secrets/{secret_id}`

- operationId: `delete_project_secret`
- summary: Delete one file-mounted secret.
- tags: `Environments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `secret_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Secret deleted
  - `401`: Unauthorized
  - `404`: Secret not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/services/{service_id}/audit-env/seed`

- operationId: `seed_convex_audit_env`
- summary: Seed `CONUSAI_API_URL` and `CONUSAI_API_TOKEN` into one Convex service
linked to this project, now.
- description: Idempotent (the Convex admin API upserts). The token is the one the
project's production environment runs with; see
`docs/how-to/audit-logging-in-an-app.md#convex`. Audited on every call,
with the outcome.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Both variables were upserted into the Convex deployment
    - `application/json`:
      - type: `object (3 properties)`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `seeded` *required*: `boolean`
        - description: `true`: the Convex backend accepted the upsert of both variables.
        - type: `boolean`
      - `service_id` *required*: `integer`
        - type: `integer`
  - `400`: The service is not a Convex service
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace, or the service is not linked to it
  - `500`: Internal server error
  - `502`: The values could not be resolved, or the Convex backend did not accept the update

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replay/settings`

- operationId: `get_session_replay_settings`
- summary: The project's session-replay retention and edge tracking mode.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Replay retention and edge tracking mode
    - `application/json`:
      - type: `object (5 properties)`
      - `default_retention_hours` *required*: `integer`
        - type: `integer`
      - `edge_tracking` *required*: `string`
        - description: `observe_settings.edge_tracking` (ADR-033 D6 amendment, 2026-10-27):
        - type: `string`
      - `max_retention_hours` *required*: `integer`
        - type: `integer`
      - `min_retention_hours` *required*: `integer`
        - type: `integer`
      - `retention_hours` *required*: `integer`
        - description: Hours a session is kept after it started.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replay/settings`

- operationId: `put_session_replay_settings`
- summary: Set the project's session-replay retention, its edge tracking mode, or
both. Changing `edge_tracking`, or setting a retention under 24 hours,
needs an organization owner or admin; a mode change is audited
(`OBSERVE_EDGE_TRACKING_UPDATED`).
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `edge_tracking`: `string | null`
      - type: `string | null`
    - `retention_hours`: `['integer', 'null']`
      - description: Hours a session is kept after it started: 1 to 2160 (90 days). The
      - type: `['integer', 'null']`
- responses:
  - `200`: Updated settings
    - `application/json`:
      - type: `object (5 properties)`
      - `default_retention_hours` *required*: `integer`
        - type: `integer`
      - `edge_tracking` *required*: `string`
        - description: `observe_settings.edge_tracking` (ADR-033 D6 amendment, 2026-10-27):
        - type: `string`
      - `max_retention_hours` *required*: `integer`
        - type: `integer`
      - `min_retention_hours` *required*: `integer`
        - type: `integer`
      - `retention_hours` *required*: `integer`
        - description: Hours a session is kept after it started.
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions, or edge_tracking changed or a retention under 24 hours set by someone other than an organization owner or admin
  - `404`: Project not found
  - `422`: Retention outside 1 to 2160 hours, an unknown edge_tracking mode, or no field set
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replay/user-erasures`

- operationId: `erase_user_session_replays`
- summary: Hard-delete every session replay of one application user (the `user_id`
the app passed to `identify`) in a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `user_id` *required*: `string`
      - description: The `user_id` the application passed to `identify`.
      - type: `string`
- responses:
  - `200`: Every session of the user deleted (possibly none)
    - `application/json`:
      - type: `object (1 properties)`
      - `sessions_deleted` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found
  - `422`: Empty or over-long user id
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replays`

- operationId: `list_project_session_replays`
- summary: List session replays using the project proven by the URL scope.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Project session replays
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `sessions` *required*: `array<object (30 properties)>`
        - type: `array<object (30 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replays/{session_replay_id}/markers`

- operationId: `get_session_replay_markers`
- summary: The replay's error and trace markers (observe-sdk P1.5): the session's
error events and the distinct trace ids of its analytics events, each with
a timeline offset in milliseconds from the session start. P3.3's player
renders them; P5.5 fills the `annotations` slot.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_replay_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Replay markers
    - `application/json`:
      - type: `object (5 properties)`
      - `annotations` *required*: `array<any>`
        - type: `array<any>`
      - `errors` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `session_replay_id` *required*: `string`
        - type: `string`
      - `started_at` *required*: `string`
        - description: Session start (RFC 3339); offsets are relative to it.
        - type: `string`
      - `traces` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/session-replays/{session_replay_id}/summary`

- operationId: `get_session_replay_summary`
- summary: Summarize one session replay of a path-scoped project (P4.3): metadata
plus capped, windowed clicks, navigations, console errors and network
failures. Never the rrweb recording.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_replay_id` (path) *required*: `string`
  - `around_ts` (query): `integer`
  - `window_s` (query): `integer`
  - `include` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Derived summary
    - `application/json`:
      - type: `object (3 properties)`
      - `events` *required*: `array<object (3 properties)>`
        - description: At most 200 moments, in time order
        - type: `array<object (3 properties)>`
      - `session` *required*: `object (6 properties)`
        - description: Session metadata carried with a summary.
        - type: `object (6 properties)`
      - `total_in_window` *required*: `integer`
        - description: Moments in the window before the cap
        - type: `integer`
  - `400`: Unknown include family
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/sessions/{session_id}/events`

- operationId: `get_session_events`
- summary: The events of one session, below the project that owns it.
- description: The legacy twin takes its project id from `?project_id=`; here it comes from
the path, and [`V1SessionEventsQuery`] has no field that could disagree.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `session_id` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved session events
    - `application/json`:
      - type: `object (3 properties)`
      - `events` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `session_id` *required*: `string`
        - type: `string`
      - `total_events` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session or project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/settings`

- operationId: `update_project_settings`
- summary: Update a project's settings.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (19 properties)`
    - `ai_alert_summaries_enabled`: `['boolean', 'null']`
      - description: Opt in to AI summarization of metric alert notifications (ADR-021).
      - type: `['boolean', 'null']`
    - `ai_debug_chat_enabled`: `['boolean', 'null']`
      - description: Opt in to AI debugging chat, e.g. on deployment failures (ADR-023).
      - type: `['boolean', 'null']`
    - `ai_write_actions_enabled`: `['boolean', 'null']`
      - description: Opt in to AI propose-then-confirm write capability.
      - type: `['boolean', 'null']`
    - `attack_mode`: `['boolean', 'null']`
      - description: Enable/disable attack mode (CAPTCHA protection) for all project environments
      - type: `['boolean', 'null']`
    - `cross_project_trace_sharing`: `['boolean', 'null']`
      - description: ADR-027 Phase 3 opt-out: set to false to suppress this project's traces
      - type: `['boolean', 'null']`
    - `directory`: `['string', 'null']`
      - type: `['string', 'null']`
    - `enable_preview_environments`: `['boolean', 'null']`
      - description: Enable automatic preview environment creation for each branch
      - type: `['boolean', 'null']`
    - `error_source_context_enabled`: `['boolean', 'null']`
      - description: Opt in to native error-tracking source context (source-file upload +
      - type: `['boolean', 'null']`
    - `error_source_root`: `['string', 'null']`
      - description: Set the auto-capture source root (relative to the checkout). Send an
      - type: `['string', 'null']`
    - `git_provider_connection_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `main_branch`: `['string', 'null']`
      - type: `['string', 'null']`
    - `preset`: `['string', 'null']`
      - type: `['string', 'null']`
    - `preset_config`: `object (2 properties) | object | object (4 properties) | null`
      - type: `object (2 properties) | object | object (4 properties) | null`
    - `preview_envs_idle_timeout_seconds`: `['integer', 'null']`
      - description: Idle timeout (seconds, 60..=86400) for on-demand preview environments.
      - type: `['integer', 'null']`
    - `preview_envs_on_demand`: `['boolean', 'null']`
      - description: When true, newly-created preview environments default to on-demand mode.
      - type: `['boolean', 'null']`
    - `preview_envs_wake_timeout_seconds`: `['integer', 'null']`
      - description: Wake timeout (seconds, 5..=120) for on-demand preview environments.
      - type: `['integer', 'null']`
    - `repo_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `repo_owner`: `['string', 'null']`
      - type: `['string', 'null']`
    - `slug`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Project settings updated
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills`

- operationId: `list_skills`
- summary: List a project's skill definitions.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Skill definitions for the project
    - `application/json`:
      - type: `object (2 properties)`
      - `items` *required*: `array<object (9 properties)>`
        - type: `array<object (9 properties)>`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills`

- operationId: `create_skill`
- summary: Create a skill definition in a project.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `content` *required*: `string`
      - type: `string`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `slug` *required*: `string`
      - type: `string`
- responses:
  - `201`: Skill created
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Skill already exists

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills/upload`

- operationId: `upload_skill`
- summary: Upload a skill definition archive.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: Skill created from the uploaded archive
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `400`: Malformed archive
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: Skill already exists

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills/{slug}`

- operationId: `get_skill`
- summary: Get one skill definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Skill definition
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or skill not found in this workspace

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills/{slug}`

- operationId: `update_skill`
- summary: Update a skill definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `content`: `['string', 'null']`
      - type: `['string', 'null']`
    - `description`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Skill updated
    - `application/json`:
      - type: `object (9 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `description`: `['string', 'null']`
        - type: `['string', 'null']`
      - `has_archive` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or skill not found in this workspace

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills/{slug}`

- operationId: `delete_skill`
- summary: Delete a skill definition by slug.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Skill deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or skill not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/skills/{slug}/archive`

- operationId: `download_skill_archive`
- summary: Download a skill definition's archive.
- tags: `Agents v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Gzipped skill archive
    - `application/gzip`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, skill or archive not found in this workspace

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/source`

- operationId: `change_project_source`
- summary: Change a project's source type.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `source_type` *required*: `string`
      - description: Source type for project deployments
      - type: `string`
- responses:
  - `200`: Source type changed
    - `application/json`:
      - type: `object (28 properties)`
      - `ai_alert_summaries_enabled` *required*: `boolean`
        - description: Opt-in to AI summarization of metric alert notifications (false = off).
        - type: `boolean`
      - `ai_debug_chat_enabled` *required*: `boolean`
        - description: Opt-in to AI debugging chat, e.g. on deployment failures (false = off).
        - type: `boolean`
      - `ai_write_actions_enabled` *required*: `boolean`
        - description: Opt-in to AI propose-then-confirm write capability (false = off).
        - type: `boolean`
      - `attack_mode` *required*: `boolean`
        - description: Attack mode - when enabled, requires CAPTCHA verification for all project environments
        - type: `boolean`
      - `created_at` *required*: `integer`
        - type: `integer`
      - `cross_project_trace_sharing` *required*: `boolean`
        - description: ADR-027 Phase 3 opt-out: when false, this project's traces are suppressed
        - type: `boolean`
      - `deployment_config` *required*: `object (23 properties)`
        - description: Deployment configuration shared between projects and environments
        - type: `object (23 properties)`
      - `directory` *required*: `string`
        - type: `string`
      - `enable_preview_environments` *required*: `boolean`
        - description: Enable automatic preview environment creation for each branch
        - type: `boolean`
      - `error_source_context_enabled` *required*: `boolean`
        - description: Opt-in to native error-tracking source context (false = off). When on,
        - type: `boolean`
      - `error_source_root`: `['string', 'null']`
        - description: Where auto-capture reads source from (relative to the checkout). Null =
        - type: `['string', 'null']`
      - `git_provider_connection_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `git_url`: `['string', 'null']`
        - description: Git clone URL for the repository (used for public repos without a provider connection)
        - type: `['string', 'null']`
      - `gitlab_webhook_id`: `['integer', 'null']`
        - description: GitLab webhook ID installed on the connected repository.
        - type: `['integer', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_deployment`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `main_branch` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `preset`: `['string', 'null']`
        - type: `['string', 'null']`
      - `preset_config`: `any`
        - description: Preset-specific configuration (Dockerfile path, build context, etc.)
        - type: `any`
      - `preview_envs_idle_timeout_seconds` *required*: `integer`
        - description: Idle timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `preview_envs_on_demand` *required*: `boolean`
        - description: When true, newly-created preview environments default to on-demand mode
        - type: `boolean`
      - `preview_envs_wake_timeout_seconds` *required*: `integer`
        - description: Wake timeout (seconds) for on-demand preview environments.
        - type: `integer`
      - `repo_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `repo_owner`: `['string', 'null']`
        - type: `['string', 'null']`
      - `slug` *required*: `string`
        - type: `string`
      - `source_type` *required*: `string`
        - description: Source type for project deployments
        - type: `string`
      - `updated_at` *required*: `integer`
        - type: `integer`
  - `400`: Invalid source type change (e.g. switching to Git here)
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/source-map-releases`

- operationId: `list_releases`
- summary: List the releases that have source maps in one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of releases
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/source-maps/{source_map_id}`

- operationId: `delete_source_map`
- summary: Delete one source map by id, in one path-scoped project.
- tags: `source-maps-v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `source_map_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Source map deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Source map not found in this project

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/static-bundles`

- operationId: `list_static_bundles`
- summary: List a project's uploaded static bundles.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Static bundles for the project
    - `application/json`:
      - type: `object (4 properties)`
      - `data` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/static-bundles/{bundle_id}`

- operationId: `get_static_bundle`
- summary: Read one static bundle.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `bundle_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Bundle details
    - `application/json`:
      - type: `object (11 properties)`
      - `blob_path` *required*: `string`
        - type: `string`
      - `checksum`: `['string', 'null']`
        - type: `['string', 'null']`
      - `content_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `format`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `metadata`: `any`
        - type: `any`
      - `original_filename`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `size_bytes` *required*: `integer`
        - type: `integer`
      - `uploaded_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or bundle not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/static-bundles/{bundle_id}`

- operationId: `delete_static_bundle`
- summary: Delete a static bundle.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `bundle_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Bundle deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project or bundle not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/status`

- operationId: `get_status_overview`
- summary: Status overview for one project.
- tags: `Status Page v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Status overview
    - `application/json`:
      - type: `object (5 properties)`
      - `brand_accent_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `brand_primary_color`: `['string', 'null']`
        - type: `['string', 'null']`
      - `monitors` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `recent_incidents` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}`

- operationId: `support_get_conversation`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Conversation
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/close`

- operationId: `support_close`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `expected_owner_version` *required*: `integer`
      - type: `integer`
    - `reason` *required*: `string`
      - type: `string`
- responses:
  - `200`: Conversation closed; conversation.closed persisted
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Lost optimistic concurrency: https://conusai.com/probs/support-owner-changed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/coding-tasks`

- operationId: `support_create_coding_task`
- summary: Start a coding task from a permitted conversation and a person's brief.
A governed MCP call waits for browser confirmation before this operation
is replayed. It returns identifiers only; status notes use CT4.2 privately.
- tags: `Support`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `agent_slug` *required*: `string`
      - type: `string`
    - `brief` *required*: `string`
      - description: Person-written report data; do not include contact data or credentials.
      - type: `string`
- responses:
  - `202`: Coding task admitted
    - `application/json`:
      - type: `object (2 properties)`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `run_id` *required*: `integer`
        - type: `integer`
  - `400`: Invalid coding handoff
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Authentication required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: Support capability or agent budget unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires a person with current project-write permission
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Resource unavailable in the caller's scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Run cooldown or concurrency limit
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `501`: Coding admission adapter not bound
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/messages`

- operationId: `support_reply`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `Idempotency-Key` (header) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `attachments`: `array<string>`
      - description: Files uploaded to this conversation by the sender and not yet sent,
      - type: `array<string>`
    - `content` *required*: `string`
      - description: The text; may be empty when the message carries attachments.
      - type: `string`
    - `expected_owner_version`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `202`: Agent reply accepted; its seq
    - `application/json`:
      - type: `object (12 properties)`
      - `attachments`: `array<object (4 properties)>`
        - description: The files the message carries, in upload order.
        - type: `array<object (4 properties)>`
      - `author_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `author_kind` *required*: `string`
        - type: `string`
      - `content` *required*: `string`
        - type: `string`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - type: `string`
      - `metadata` *required*: `any`
        - type: `any`
      - `seq` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `visibility` *required*: `string`
        - type: `string`
  - `400`: Missing or malformed Idempotency-Key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Idempotency-Key already names a different canonical request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/reply-emails`

- operationId: `support_list_reply_emails`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The reply mails of the conversation's agent replies (S3.5a), newest first: state and reason only, no address or content
    - `application/json`:
      - type: `array<object (6 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read (in the credential itself for an API key)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/tool-actions/{action_id}/confirm`

- operationId: `support_confirm_tool_action`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `action_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Confirmed and run as the agent for the conversation's contact
    - `application/json`:
      - type: `object (2 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - description: `executed`, `failed`, `refused` or `rejected`.
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via a browser session; or refused at confirm
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for an unknown action, conversation or scope, or a delegation that no longer resolves
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Already decided
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/conversations/{id}/tool-actions/{action_id}/reject`

- operationId: `support_reject_tool_action`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `action_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Rejected; nothing ran
    - `application/json`:
      - type: `object (2 properties)`
      - `action_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - description: `executed`, `failed`, `refused` or `rejected`.
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via a browser session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for an unknown action, conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Already decided
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/support/inbox`

- operationId: `support_list_conversations`
- tags: `Support Inbox`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `filter` (query): `string`
  - `channel_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Inbox rows, oldest first
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `400`: Unknown filter
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/trigger-pipeline`

- operationId: `trigger_project_pipeline`
- summary: Trigger a deployment pipeline for a project.
- description: `intent: redeploy` (the console's Redeploy) deploys a commit again even
when it is already live in the environment.
- tags: `Projects v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `branch`: `['string', 'null']`
      - type: `['string', 'null']`
    - `commit`: `['string', 'null']`
      - type: `['string', 'null']`
    - `environment_id` *required*: `integer`
      - description: Required environment ID. Select an active environment belonging to this project.
      - type: `integer`
    - `intent`: `string`
      - description: `deploy` (the default): refused with 409 `duplicate-deployment` while the
      - type: `string`
    - `tag`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Pipeline triggered
    - `application/json`:
      - type: `object (6 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit`: `['string', 'null']`
        - type: `['string', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `message` *required*: `string`
        - type: `string`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `tag`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: No environment specified, or environment not in this project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `409`: `https://conusai.com/probs/duplicate-deployment`: the commit is already in flight in this environment (a pending, running or deploying deployment, or a queued one with no deployment yet, `deployment_state` `queued` and null `deployment_id`/`deployment_slug`), or is the environment's live deployment (its current one, `completed`; the commit of an older, replaced deployment is a rollback and is accepted); nothing was queued. The problem names it (`deployment_id`, `deployment_slug`, `deployment_state`, `commit`). With `intent` `redeploy` only a commit in flight is refused: the live commit is deployed again
  - `422`: `https://conusai.com/probs/commit-not-on-git-server`: an explicit `commit` the project's git server does not hold (it was not pushed yet); nothing was queued. The problem names it (`commit`). Asked of the provider's API; a connection without one leaves the check to the download
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/unique-counts`

- operationId: `get_unique_counts`
- summary: Unique visitor/session counts for one project.
- tags: `Events v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `start_date` (query) *required*: `string`
  - `end_date` (query) *required*: `string`
  - `environment_id` (query): `integer`
  - `deployment_id` (query): `integer`
  - `metric` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Successfully retrieved unique counts
    - `application/json`:
      - type: `object (1 properties)`
      - `count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/upload/static`

- operationId: `upload_static_bundle`
- summary: Upload a static bundle for later deployment.
- description: `Multipart` consumes the request body, so it is the **last** extractor here
exactly as it is on the legacy twin. The route carries
`DefaultBodyLimit::max(UPLOAD_LIMIT)` for the same reason the legacy one
does.
- tags: `Deployments v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: Bundle uploaded
    - `application/json`:
      - type: `object (11 properties)`
      - `blob_path` *required*: `string`
        - type: `string`
      - `checksum`: `['string', 'null']`
        - type: `['string', 'null']`
      - `content_type` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `format`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `metadata`: `any`
        - type: `any`
      - `original_filename`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `size_bytes` *required*: `integer`
        - type: `integer`
      - `uploaded_at` *required*: `string`
        - type: `string`
  - `400`: Invalid request or unsupported format
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `413`: Bundle too large
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays`

- operationId: `list_visitor_session_replays`
- summary: List the session replays of one visitor in a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Visitor session replays
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `sessions` *required*: `array<object (30 properties)>`
        - type: `array<object (30 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays`

- operationId: `erase_visitor_session_replays`
- summary: Hard-delete every session replay of one visitor in a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Every session of the visitor deleted
    - `application/json`:
      - type: `object (1 properties)`
      - `sessions_deleted` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Visitor not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays/{session_id}`

- operationId: `get_session_replay`
- summary: Read one session replay of a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `session_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Session replay details
    - `application/json`:
      - type: `object (1 properties)`
      - `session` *required*: `object (30 properties)`
        - type: `object (30 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays/{session_id}`

- operationId: `delete_session_replay`
- summary: Delete one session replay in a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `session_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Session replay deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays/{session_id}/duration`

- operationId: `update_session_duration`
- summary: Update the duration of one session replay in a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `session_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `duration` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Duration updated
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/visitors/{visitor_id}/session-replays/{session_id}/events`

- operationId: `get_session_replay_events`
- summary: Read one session replay with events of a path-scoped project.
- tags: `Session Replay v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `visitor_id` (path) *required*: `integer`
  - `session_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Session replay with events
    - `application/json`:
      - type: `object (2 properties)`
      - `events` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `session` *required*: `object (30 properties)`
        - type: `object (30 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Session not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans`

- operationId: `list_project_scans`
- summary: List a project's vulnerability scans.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of vulnerability scans
    - `application/json`:
      - type: `object (4 properties)`
      - `data` *required*: `array<object (20 properties)>`
        - type: `array<object (20 properties)>`
      - `page` *required*: `integer`
        - type: `integer`
      - `page_size` *required*: `integer`
        - type: `integer`
      - `total` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans`

- operationId: `trigger_scan`
- summary: Trigger a scan of the project's current deployment in one environment.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `environment_id` *required*: `integer`
      - description: Environment ID to scan (uses the current deployment for this environment)
      - type: `integer`
- responses:
  - `202`: Scan triggered successfully
    - `application/json`:
      - type: `object (3 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `scan_id` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project, environment or deployment not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans/environments`

- operationId: `get_latest_scans_per_environment`
- summary: The latest scan of each environment's current deployment.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Latest scans per environment
    - `application/json`:
      - type: `array<object (20 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans/latest`

- operationId: `get_latest_scan`
- summary: The project's most recent completed scan.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `environment_id` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Latest scan for project
    - `application/json`:
      - type: `object (20 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `critical_count` *required*: `integer`
        - type: `integer`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `high_count` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `low_count` *required*: `integer`
        - type: `integer`
      - `medium_count` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `scanner_type` *required*: `string`
        - type: `string`
      - `scanner_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `total_count` *required*: `integer`
        - type: `integer`
      - `unknown_count` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found, or no scans yet
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans/{scan_id}`

- operationId: `get_scan`
- summary: Read one scan below the proven project.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `scan_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Scan details
    - `application/json`:
      - type: `object (20 properties)`
      - `branch`: `['string', 'null']`
        - type: `['string', 'null']`
      - `commit_hash`: `['string', 'null']`
        - type: `['string', 'null']`
      - `completed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `critical_count` *required*: `integer`
        - type: `integer`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `high_count` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `low_count` *required*: `integer`
        - type: `integer`
      - `medium_count` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `scanner_type` *required*: `string`
        - type: `string`
      - `scanner_version`: `['string', 'null']`
        - type: `['string', 'null']`
      - `started_at` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `total_count` *required*: `integer`
        - type: `integer`
      - `unknown_count` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Scan not found in this project
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans/{scan_id}`

- operationId: `delete_scan`
- summary: Delete a scan below the proven project.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `scan_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Scan deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Scan not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/vulnerability-scans/{scan_id}/vulnerabilities`

- operationId: `get_scan_vulnerabilities`
- summary: A scan's vulnerabilities, below the proven project.
- tags: `Vulnerability Scans v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `scan_id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
  - `severity` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: List of vulnerabilities
    - `application/json`:
      - type: `array<object (18 properties)>`
  - `400`: Invalid severity filter
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Scan not found in this project
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks`

- operationId: `list_webhooks`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of webhooks
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks`

- operationId: `create_webhook`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `enabled`: `['boolean', 'null']`
      - description: Whether the webhook is enabled
      - type: `['boolean', 'null']`
    - `events` *required*: `array<string>`
      - description: Event types to subscribe to: kernel events (`deployment.created`) and
      - type: `array<string>`
    - `secret`: `['string', 'null']`
      - description: Secret for HMAC signature verification (optional)
      - type: `['string', 'null']`
    - `url` *required*: `string`
      - description: Target URL for webhook delivery
      - type: `string`
- responses:
  - `201`: Webhook created
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - type: `array<string>`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `404`: Project not found in this workspace
  - `422`: An event type is neither a kernel event nor declared by a service enabled for the organization (`urn:conusai:webhooks:unknown-event`)
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}`

- operationId: `get_webhook`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Webhook details
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - type: `array<string>`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Webhook not found
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}`

- operationId: `update_webhook`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `enabled`: `['boolean', 'null']`
      - description: Whether the webhook is enabled
      - type: `['boolean', 'null']`
    - `events`: `['array', 'null']`
      - description: Event types to subscribe to, as on create.
      - type: `['array', 'null']`
    - `secret`: `['string', 'null']`
      - description: Secret for HMAC signature verification
      - type: `['string', 'null']`
    - `url`: `['string', 'null']`
      - description: Target URL for webhook delivery
      - type: `['string', 'null']`
- responses:
  - `200`: Webhook updated
    - `application/json`:
      - type: `object (8 properties)`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - type: `array<string>`
      - `has_secret` *required*: `boolean`
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `404`: Webhook not found
  - `422`: An event type is neither a kernel event nor declared by a service enabled for the organization (`urn:conusai:webhooks:unknown-event`)
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}`

- operationId: `delete_webhook`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Webhook deleted
  - `401`: Unauthorized
  - `404`: Webhook not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}/app-binding`

- operationId: `bind_app_webhook`
- tags: `Webhooks`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `binding_id` *required*: `string`
      - type: `string`
    - `environment_id` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Exact audience already exists
  - `201`: Immutable audience created
  - `403`: Project administration required
  - `409`: Current binding/grants unavailable
  - `503`: Canonical audit unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}/deliveries`

- operationId: `list_deliveries`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of deliveries
    - `application/json`:
      - type: `array<object (14 properties)>`
  - `401`: Unauthorized
  - `404`: Webhook not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}/deliveries/{delivery_id}`

- operationId: `get_delivery`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
  - `delivery_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Delivery details including full payload
    - `application/json`:
      - type: `object (14 properties)`
      - `attempt_number` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `delivered_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `event_id` *required*: `string`
        - type: `string`
      - `event_type` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_error_code`: `['string', 'null']`
        - description: The stable code of the last failed attempt (e.g. `http_status`,
        - type: `['string', 'null']`
      - `next_attempt_at`: `['string', 'null']`
        - description: When the next attempt is due (`pending` only).
        - type: `['string', 'null']`
      - `payload` *required*: `string`
        - description: JSON payload that was sent to the webhook endpoint
        - type: `string`
      - `state` *required*: `string`
        - description: Durable delivery state: `pending` (queued or waiting for a retry),
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `webhook_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Delivery not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/webhooks/{webhook_id}/deliveries/{delivery_id}/retry`

- operationId: `retry_delivery`
- tags: `Webhooks v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `webhook_id` (path) *required*: `integer`
  - `delivery_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Delivery retried
    - `application/json`:
      - type: `object (14 properties)`
      - `attempt_number` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `delivered_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `event_id` *required*: `string`
        - type: `string`
      - `event_type` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_error_code`: `['string', 'null']`
        - description: The stable code of the last failed attempt (e.g. `http_status`,
        - type: `['string', 'null']`
      - `next_attempt_at`: `['string', 'null']`
        - description: When the next attempt is due (`pending` only).
        - type: `['string', 'null']`
      - `payload` *required*: `string`
        - description: JSON payload that was sent to the webhook endpoint
        - type: `string`
      - `state` *required*: `string`
        - description: Durable delivery state: `pending` (queued or waiting for a retry),
        - type: `string`
      - `status_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `success` *required*: `boolean`
        - type: `boolean`
      - `webhook_id` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
  - `404`: Delivery not found
  - `409`: The delivery worker is attempting this delivery
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/{name}/{path}`

- operationId: `project_service_route`
- summary: A request for a project-level service:
`/v1/orgs/{org_slug}/workspaces/{workspace_slug}/projects/{project_slug}/{name}/…`.
- tags: `Service gateway`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization's plan does not include the service
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The licence is degraded, or the service is not rolled out to this organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The project does not exist or the caller cannot see it; (`type` `urn:conusai:service:not-enabled`) the service is not installed or not enabled; or no such route
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: (`type` `urn:conusai:service:unavailable`) the service runs on a host that cannot be reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes`

- operationId: `list_sandboxes`
- summary: List the sandboxes of one workspace.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `page` (query): `integer`
  - `page_size` (query): `integer`
  - `limit` (query): `integer`
  - `project` (query): `string`
  - `since` (query): `integer`
  - `until` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Sandboxes in the workspace
    - `application/json`:
      - type: `object (2 properties)`
      - `pagination` *required*: `object (3 properties)`
        - description: SDK pagination cursor. We use opaque page numbers internally but
        - type: `object (3 properties)`
      - `sandboxes` *required*: `array<object (18 properties)>`
        - type: `array<object (18 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization or workspace not found

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes`

- operationId: `create_sandbox`
- summary: Create a sandbox inside one workspace.
- description: The organization and workspace come from the path, never from the body: a
request body cannot place a sandbox in another tenant.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (17 properties)`
    - `_runtime`: `['string', 'null']`
      - type: `['string', 'null']`
    - `backend`: `['string', 'null']`
      - description: Isolation backend: `"docker"` (default) or `"firecracker"` (ADR-029,
      - type: `['string', 'null']`
    - `cpu_limit`: `['number', 'null']`
      - type: `['number', 'null']`
    - `disk_size_mb`: `['integer', 'null']`
      - description: Root disk size in MB (Firecracker only; Docker ignores it). Omit for
      - type: `['integer', 'null']`
    - `env`: `object`
      - description: Extra env vars baked into the container on create.
      - type: `object`
    - `image`: `['string', 'null']`
      - description: Docker image override. `null` uses the platform default.
      - type: `['string', 'null']`
    - `memory_limit_mb`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `networkPolicy`: `any`
      - type: `any`
    - `pids_limit`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `ports`: `array<integer>`
      - description: Ports the sandbox will listen on. Each port becomes a `routes[]`
      - type: `array<integer>`
    - `preview_password`: `['string', 'null']`
      - description: Optional preview-URL password. When set, every preview URL served
      - type: `['string', 'null']`
    - `projectId`: `['string', 'null']`
      - type: `['string', 'null']`
    - `resources`: `object (2 properties) | null`
      - type: `object (2 properties) | null`
    - `source`: `object (7 properties) | object (2 properties) | null`
      - type: `object (7 properties) | object (2 properties) | null`
    - `timeout`: `['integer', 'null']`
      - description: Idle timeout as sent by `@vercel/sandbox` (milliseconds). Converted
      - type: `['integer', 'null']`
    - `timeout_secs`: `['integer', 'null']`
      - description: Idle timeout in seconds (conusai-native). Clamped to `[60, 86400]`.
      - type: `['integer', 'null']`
- responses:
  - `201`: Sandbox created
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}`

- operationId: `get_sandbox`
- summary: Read one sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Sandbox details
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/cmd`

- operationId: `cmd`
- summary: Run a command inside one sandbox, in the SDK's request/response shape.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `args`: `array<string>`
      - description: Arguments to pass to the binary. Defaults to empty.
      - type: `array<string>`
    - `command` *required*: `string`
      - description: Binary name (`argv[0]`) — e.g. `"ls"`, `"node"`. The SDK sends this
      - type: `string`
    - `cwd`: `['string', 'null']`
      - description: Working directory override.
      - type: `['string', 'null']`
    - `env`: `object`
      - description: Extra env vars.
      - type: `object`
    - `sudo`: `boolean`
      - description: When true, the SDK runs the command privileged. We ignore it today
      - type: `boolean`
    - `wait`: `boolean`
      - description: When true, the response is an `application/x-ndjson` stream where
      - type: `boolean`
- responses:
  - `200`: Command started (wait=false) or finished (wait=true)
    - `application/json`:
      - type: `object (1 properties)`
      - `command` *required*: `object (7 properties)`
        - description: Inner `command` object — matches the SDK's zod validator exactly.
        - type: `object (7 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/cmd/{cmd_id}`

- operationId: `get_cmd`
- summary: Read one command's current state, in the SDK's shape.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `cmd_id` (path) *required*: `string`
  - `wait` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Command snapshot
    - `application/json`:
      - type: `object (1 properties)`
      - `command` *required*: `object (7 properties)`
        - description: Inner `command` object — matches the SDK's zod validator exactly.
        - type: `object (7 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or command not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/cmd/{cmd_id}/logs`

- operationId: `cmd_logs`
- summary: Stream one command's stdout/stderr as `application/x-ndjson`.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `cmd_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: NDJSON stream of log events
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or command not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/destroy`

- operationId: `destroy_sandbox`
- summary: Destroy one sandbox. Alias of [`stop_sandbox`] with an explicit verb,
kept because the `@vercel/sandbox` SDK spells it this way.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Sandbox destroyed
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/domain`

- operationId: `domain`
- summary: Read the preview URL for one port of a sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `port` (query) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Preview URL for the port
    - `application/json`:
      - type: `object (1 properties)`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid port
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/events`

- operationId: `list_events`
- summary: The operations timeline for a sandbox, newest first.
- description: # This closes a hole the legacy route still has

`super::sandboxes::list_events` takes **no** tenant scope at all — neither
`ActiveOrg` nor a workspace — and passes the public id straight to
`list_events`, which filters on the owning `user_id` only. That check stops
a *different* user, not the same principal reading across their own
workspace selection, which is precisely the case
`m20260802_000002_scope_sandboxes_through_workspace` exists for. Here the
scoped lookup runs first, so a sandbox outside the named workspace is absent
rather than readable.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Operations timeline
    - `application/json`:
      - type: `object (1 properties)`
      - `events` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/exec`

- operationId: `exec`
- summary: Run a command inside one sandbox and wait for it.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `cmd` *required*: `array<string>`
      - type: `array<string>`
    - `cwd`: `['string', 'null']`
      - type: `['string', 'null']`
    - `env`: `object`
      - type: `object`
- responses:
  - `200`: Command finished (a non-zero exit is NOT an error)
    - `application/json`:
      - type: `object (3 properties)`
      - `exit_code` *required*: `integer`
        - type: `integer`
      - `stderr` *required*: `string`
        - type: `string`
      - `stdout` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `500`: Exec failed inside the sandbox

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/exec-detached`

- operationId: `exec_detached`
- summary: Start a command inside one sandbox without waiting for it.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `cmd` *required*: `array<string>`
      - type: `array<string>`
    - `cwd`: `['string', 'null']`
      - type: `['string', 'null']`
    - `env`: `object`
      - type: `object`
- responses:
  - `202`: Command accepted; poll the job
    - `application/json`:
      - type: `object (1 properties)`
      - `job_id` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `500`: Exec failed inside the sandbox

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/extend-timeout`

- operationId: `extend_timeout`
- summary: Push one sandbox's expiry further out.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `duration`: `['integer', 'null']`
      - description: `@vercel/sandbox`-compatible alternative — duration in milliseconds.
      - type: `['integer', 'null']`
    - `extra_secs`: `['integer', 'null']`
      - description: Extra seconds to add to the existing `expires_at` (conusai-native).
      - type: `['integer', 'null']`
- responses:
  - `200`: Timeout extended
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/fs/mkdir`

- operationId: `mkdir`
- summary: Create a directory inside a sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `path` *required*: `string`
      - type: `string`
- responses:
  - `204`: Directory created (or already existed)
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/fs/read`

- operationId: `read_file`
- summary: Read one file out of a sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `path` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: File contents (base64)
    - `application/json`:
      - type: `object (3 properties)`
      - `contents_b64` *required*: `string`
        - description: File contents, base64-encoded. Symmetric with `WriteFileBody`.
        - type: `string`
      - `path` *required*: `string`
        - type: `string`
      - `size` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or file not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/fs/stat`

- operationId: `stat_path`
- summary: Stat one path inside a sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `path` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Stat info (exists=false when missing is not an error)
    - `application/json`:
      - type: `object (5 properties)`
      - `exists` *required*: `boolean`
        - type: `boolean`
      - `is_dir` *required*: `boolean`
        - type: `boolean`
      - `is_file` *required*: `boolean`
        - type: `boolean`
      - `path` *required*: `string`
        - type: `string`
      - `size` *required*: `integer`
        - type: `integer`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/fs/write`

- operationId: `write_file`
- summary: Write one file, or a gzipped tar of files, into a sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `contents_b64` *required*: `string`
      - description: File contents, base64-encoded. Required — lets callers ship binary
      - type: `string`
    - `mode`: `['integer', 'null']`
      - description: Unix permission mask (e.g. 0o644). Defaults to 0o644 when absent.
      - type: `['integer', 'null']`
    - `path` *required*: `string`
      - description: Absolute path inside the sandbox. Must start with `/`.
      - type: `string`
- responses:
  - `204`: File(s) written
  - `400`: Validation error or invalid base64
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `415`: Unsupported Content-Type

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/fs/write-batch`

- operationId: `write_files`
- summary: Write several files into a sandbox in one request.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `files` *required*: `array<object (3 properties)>`
      - description: List of files to write. Each entry must include an absolute
      - type: `array<object (3 properties)>`
- responses:
  - `200`: All files written
    - `application/json`:
      - type: `object (1 properties)`
      - `written` *required*: `integer`
        - description: Number of files successfully written before the first failure
        - type: `integer`
  - `400`: Validation error or invalid base64
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/jobs`

- operationId: `list_jobs`
- summary: List one sandbox's detached jobs.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Detached jobs
    - `application/json`:
      - type: `object (1 properties)`
      - `items` *required*: `array<object (6 properties)>`
        - type: `array<object (6 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/jobs/{job_id}`

- operationId: `job_status`
- summary: Read one detached job's status snapshot.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `job_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Job status snapshot
    - `application/json`:
      - type: `object (5 properties)`
      - `exit_code`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `stderr` *required*: `string`
        - type: `string`
      - `stdout` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or job not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/jobs/{job_id}/kill`

- operationId: `kill_job`
- summary: Terminate one detached job.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `job_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `force`: `boolean`
      - description: When true, sends SIGKILL immediately. Defaults to SIGTERM so the
      - type: `boolean`
- responses:
  - `204`: Job killed
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or job not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/jobs/{job_id}/logs`

- operationId: `job_logs`
- summary: Stream one detached job's stdout/stderr as server-sent events.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `job_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: SSE stream of log events
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or job not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/pause`

- operationId: `pause_sandbox`
- summary: Pause one sandbox (container stopped, state preserved).
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Sandbox paused
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `409`: Sandbox is in an incompatible state

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/preview-password`

- operationId: `set_preview_password`
- summary: Set or rotate one sandbox's preview password.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `password` *required*: `string`
      - description: Plaintext password to protect the sandbox's preview URLs. Hashed
      - type: `string`
- responses:
  - `200`: Preview password set or rotated
    - `application/json`:
      - type: `object (1 properties)`
      - `preview_password_hint` *required*: `string`
        - description: Last 4 chars of the password we just stored. Surface in the UI so
        - type: `string`
  - `400`: Password too short or too long
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/preview-password`

- operationId: `clear_preview_password`
- summary: Remove one sandbox's preview password.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Preview password removed
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/resize`

- operationId: `resize_sandbox`
- summary: Grow a sandbox's root disk. Offline resize — the VM reboots.
- description: Same story as [`list_events`]: the legacy `resize_sandbox` route carries
no tenant scope whatsoever, so the workspace lookup below is the check being
added rather than a duplicate of one.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `disk_size_mb` *required*: `integer`
      - description: New root disk size in MB. Grow-only; must exceed the current size.
      - type: `integer`
- responses:
  - `200`: Resized
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `400`: Invalid size or unsupported backend
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/restart`

- operationId: `restart_sandbox`
- summary: Restart one sandbox's container in place.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Sandbox restarted
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `409`: Sandbox is stopped (use /resume) or already destroyed

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/resume`

- operationId: `resume_sandbox`
- summary: Resume one paused sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Sandbox resumed
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `409`: Sandbox is not in a resumable state

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/source`

- operationId: `source_sandbox`
- summary: Seed source content into one sandbox's work directory.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties) | object (2 properties)`
- responses:
  - `200`: Source seeded
    - `application/json`:
      - type: `object (2 properties)`
      - `routes` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sandbox` *required*: `object (18 properties)`
        - description: Inner `sandbox` object in `@vercel/sandbox` responses. Strict shape —
        - type: `object (18 properties)`
  - `400`: Validation error
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace
  - `409`: Sandbox is not running
  - `500`: Source seed failed inside sandbox

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/stop`

- operationId: `stop_sandbox`
- summary: Stop and destroy one sandbox.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Sandbox stopped and destroyed
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox not found in this workspace

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/sandboxes/{id}/{cmd_id}/kill`

- operationId: `cmd_kill`
- summary: Kill one running command, in the SDK's shape.
- tags: `Sandboxes v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `cmd_id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `force`: `boolean`
      - description: Optional: when true, SIGKILL instead of SIGTERM.
      - type: `boolean`
- responses:
  - `200`: Command killed; final snapshot
    - `application/json`:
      - type: `object (1 properties)`
      - `command` *required*: `object (7 properties)`
        - description: Inner `command` object — matches the SDK's zod validator exactly.
        - type: `object (7 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Sandbox or command not found in this workspace

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services`

- operationId: `list_services`
- summary: List the managed services of one workspace.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Managed services in the workspace
    - `application/json`:
      - type: `array<object (13 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services`

- operationId: `create_service`
- summary: Create an managed service in a workspace.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `members`: `array<object (2 properties)>`
      - description: Cluster member specifications. Required when topology is "cluster".
      - type: `array<object (2 properties)>`
    - `name` *required*: `string`
      - type: `string`
    - `node_id`: `['integer', 'null']`
      - description: Target node ID for the service. Omit or null to run on the control plane.
      - type: `['integer', 'null']`
    - `parameters` *required*: `object`
      - type: `object`
    - `service_type` *required*: `string`
      - type: `string`
    - `topology`: `string`
      - description: Service topology: "standalone" (default) or "cluster" (HA multi-member).
      - type: `string`
    - `version`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `201`: Service created
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/by-slug/{slug}`

- operationId: `get_service_by_slug`
- summary: Read one managed service by its slug.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Managed service details
    - `application/json`:
      - type: `object (3 properties)`
      - `current_parameters`: `['object', 'null']`
        - description: Typed parameter values (booleans, numbers, strings) as stored in the
        - type: `['object', 'null']`
      - `parameter_schema`: `any`
        - type: `any`
      - `service` *required*: `object (13 properties)`
        - type: `object (13 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/health-status-batch`

- operationId: `list_service_health_statuses`
- summary: Current health status of every managed service in the workspace.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Batch of current health statuses
    - `application/json`:
      - type: `object (1 properties)`
      - `statuses` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Organization or workspace not found
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/projects/{project_id}`

- operationId: `list_project_services`
- summary: List the managed services linked to one project.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `project_id` (path) *required*: `integer`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of services linked to project
    - `application/json`:
      - type: `array<object (4 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}`

- operationId: `get_service`
- summary: Read one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Managed service details
    - `application/json`:
      - type: `object (3 properties)`
      - `current_parameters`: `['object', 'null']`
        - description: Typed parameter values (booleans, numbers, strings) as stored in the
        - type: `['object', 'null']`
      - `parameter_schema`: `any`
        - type: `any`
      - `service` *required*: `object (13 properties)`
        - type: `object (13 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}`

- operationId: `update_service`
- summary: Update one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `docker_image`: `['string', 'null']`
      - description: Docker image to use for the service (e.g., "build.conusai.com/conusai/postgres-walg:18-bookworm", "timescale/timescaledb-ha:pg18")
      - type: `['string', 'null']`
    - `parameters` *required*: `object`
      - type: `object`
- responses:
  - `200`: Service updated
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `409`: A major upgrade is in progress for this service
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}`

- operationId: `delete_service`
- summary: Delete one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Service deleted
  - `400`: Cannot delete: service is still linked to projects
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `409`: Cannot delete: a Git service keeps its files in this store
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/cluster-health`

- operationId: `get_cluster_health`
- summary: Per-member cluster health for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Per-member cluster health report
    - `application/json`:
      - type: `object (4 properties)`
      - `checked_at` *required*: `string`
        - description: ISO-8601 wall-clock when the report was generated.
        - type: `string`
      - `members` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `monitor_error`: `['string', 'null']`
        - description: Set when the monitor itself was unreachable. UI shows a banner.
        - type: `['string', 'null']`
      - `monitor_response_ms` *required*: `integer`
        - description: Round-trip to query the monitor (ms).
        - type: `integer`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/configuration/{parameter}/reveal`

- operationId: `reveal_service_parameter`
- summary: Reveal one declared secret parameter after browser-session step-up.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `parameter` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The requested secret parameter
    - `application/json`:
      - type: `object (2 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `value` *required*: `any`
        - type: `any`
  - `401`: Authenticated browser session required
  - `403`: Insufficient permission or fresh step-up required
  - `404`: Service or secret parameter not found in this workspace
  - `428`: Fresh session verification required
  - `500`: Authorization, decryption, or audit failed
  - `503`: Sensitive-action policy unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/convex/admin-key`

- operationId: `get_convex_admin_key`
- summary: Reveal the admin key of a self-hosted Convex service.
- description: Guarded exactly like [`reveal_service_parameter`]: browser session only,
workspace admin, fresh step-up, and a fail-closed audit record — this is
the discrete "reveal the secret" action, unlike [`get_service`], which
fires on every page load.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Convex admin key
    - `application/json`:
      - type: `object (3 properties)`
      - `admin_key` *required*: `string`
        - type: `string`
      - `self_hosted_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `site_url`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Service is not a convex service, or its admin key is not available yet
  - `401`: Authenticated browser session required
  - `403`: Insufficient permission or fresh step-up required
  - `404`: Service not found in this workspace
  - `428`: Fresh session verification required
  - `500`: Authorization, decryption, or audit failed
  - `503`: Sensitive-action policy unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/convex/domains`

- operationId: `get_convex_connection_details`
- summary: Connection details for a self-hosted Convex service (public origins,
dashboard URL, env pair, and the routes the proxy serves). Admin key is
masked — reveal it through the audited `convex/admin-key` endpoint.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Convex connection details
    - `application/json`:
      - type: `object (15 properties)`
      - `admin_key`: `['string', 'null']`
        - description: Always `***` when a key exists, `null` when none has been issued.
        - type: `['string', 'null']`
      - `admin_key_available` *required*: `boolean`
        - type: `boolean`
      - `admin_key_reveal_path` *required*: `string`
        - type: `string`
      - `certificates` *required*: `array<object (3 properties)>`
        - description: TLS state per advertised hostname. `routed` says the proxy will accept
        - type: `array<object (3 properties)>`
      - `cloud_domain`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cloud_origin`: `['string', 'null']`
        - description: `CONVEX_CLOUD_ORIGIN` — queries and mutations.
        - type: `['string', 'null']`
      - `dashboard_origin`: `['string', 'null']`
        - type: `['string', 'null']`
      - `dashboard_reachable`: `['boolean', 'null']`
        - description: Live reachability probe through the public anchor; `null` in Mode A.
        - type: `['boolean', 'null']`
      - `env` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `routed` *required*: `boolean`
        - description: False means the hostnames exist but the proxy has no route for them —
        - type: `boolean`
      - `routes` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `site_domain`: `['string', 'null']`
        - type: `['string', 'null']`
      - `site_origin`: `['string', 'null']`
        - description: `CONVEX_SITE_ORIGIN` — HTTP actions.
        - type: `['string', 'null']`
      - `tls_ready` *required*: `boolean`
        - description: True only when *every* advertised hostname has an issued certificate.
        - type: `boolean`
  - `400`: Not a convex service
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/convex/domains`

- operationId: `attach_convex_domains`
- summary: Attach public domains to a self-hosted Convex service.
- description: The removed flat twin took no workspace at all — it gated on the
organization plus the IDOR check in `assert_service_owned_by_caller`, and
then failed closed on the deleted header transport anyway. Here the
workspace is named by the caller, so `assert_service_in_scope` runs first
and the route is strictly stronger rather than merely relocated.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `cloud_domain_id` *required*: `integer`
      - description: `domains.id` of the hostname to route to the cloud/API port (3210).
      - type: `integer`
    - `site_domain_id` *required*: `integer`
      - description: `domains.id` of the hostname to route to the HTTP-actions/site port (3211).
      - type: `integer`
- responses:
  - `200`: Domains attached
    - `application/json`:
      - type: `object (4 properties)`
      - `cloud_domain` *required*: `string`
        - type: `string`
      - `cloud_origin` *required*: `string`
        - type: `string`
      - `site_domain` *required*: `string`
        - type: `string`
      - `site_origin` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/git/read-token`

- operationId: `mint_git_read_token`
- summary: Mint a scoped `read:package` token on a Git (Gitea) service (P4.4, D13).
- description: The token is returned exactly once in this response; the platform never
persists or logs it. Audited on every successful call, like the Convex
admin-key reveal.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `name` *required*: `string`
      - description: Display name for the token (1-128 printable characters).
      - type: `string`
- responses:
  - `200`: Freshly minted read-only package token
    - `application/json`:
      - type: `object (3 properties)`
      - `scopes` *required*: `array<string>`
        - type: `array<string>`
      - `token` *required*: `string`
        - description: The freshly minted Gitea access token (scope `read:package`).
        - type: `string`
      - `token_name` *required*: `string`
        - type: `string`
  - `400`: Service is not a git service, or its bootstrap has not finished
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/health-check`

- operationId: `trigger_service_health_check`
- summary: Probe one managed service now and return the fresh snapshot.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Fresh health snapshot after probing
    - `application/json`:
      - type: `object (8 properties)`
      - `consecutive_failures` *required*: `integer`
        - description: Consecutive failed probes. Alert fires at 3.
        - type: `integer`
      - `last_checked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `recent_checks` *required*: `array<object (4 properties)>`
        - description: Most recent checks, newest-first (capped at `limit`).
        - type: `array<object (4 properties)>`
      - `response_time_ms`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `status`: `['string', 'null']`
        - description: Current health. `null` if the service has not been probed yet.
        - type: `['string', 'null']`
      - `uptime_24h_percent`: `['number', 'null']`
        - description: Uptime percentage over the last 24 hours (0.0 — 100.0).
        - type: `['number', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/health-status`

- operationId: `get_service_health_status`
- summary: Current health plus recent history for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Current health + recent history
    - `application/json`:
      - type: `object (8 properties)`
      - `consecutive_failures` *required*: `integer`
        - description: Consecutive failed probes. Alert fires at 3.
        - type: `integer`
      - `last_checked_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `recent_checks` *required*: `array<object (4 properties)>`
        - description: Most recent checks, newest-first (capped at `limit`).
        - type: `array<object (4 properties)>`
      - `response_time_ms`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `status`: `['string', 'null']`
        - description: Current health. `null` if the service has not been probed yet.
        - type: `['string', 'null']`
      - `uptime_24h_percent`: `['number', 'null']`
        - description: Uptime percentage over the last 24 hours (0.0 — 100.0).
        - type: `['number', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/grant-states`

- operationId: `list_identity_grant_states`
- summary: Desired/applied grant states of one linked environment. Workspace Admin
only: it names the subjects that may sign in to an app.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
  - `environment` (query) *required*: `string`
  - `cursor` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: One page of grant states
    - `application/json`:
      - type: `object (2 properties)`
      - `grants` *required*: `array<object (8 properties)>`
        - type: `array<object (8 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Unknown environment, bad cursor or limit, or not an identity provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/grant-states`

- operationId: `set_identity_grant_state`
- summary: Durably allow or deny one subject on one linked environment. `200` once
the provider applied the revision, `202` while it is pending. A later
stale allow can never override a newer deny: the provider enforces the
monotonic revision.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `environment` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `role` *required*: `string`
      - description: A role on one linked environment. Distinct from the earlier Zitadel
      - type: `string`
    - `state` *required*: `string`
      - description: Whether the subject may sign in to the linked environment.
      - type: `string`
    - `subject` *required*: `string`
      - description: Opaque provider subject (from the user list), never an email address.
      - type: `string`
- responses:
  - `200`: Applied by the provider
    - `application/json`:
      - type: `object (4 properties)`
      - `applied_revision` *required*: `integer`
        - type: `integer`
      - `desired_revision` *required*: `integer`
        - type: `integer`
      - `operation_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `202`: Recorded; the provider has not acknowledged it yet
    - `application/json`:
      - type: `object (4 properties)`
      - `applied_revision` *required*: `integer`
        - type: `integer`
      - `desired_revision` *required*: `integer`
        - type: `integer`
      - `operation_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Invalid subject or unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it
  - `409`: The provider does not support durable grants

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/grants`

- operationId: `grant_identity_role`
- summary: Invite a user by email and give them one role on one linked environment
of an Identity service (MIB I5).
- description: Zitadel refuses a sign-in to a linked app for a user who holds no role of
that app's project, so this is how a person reaches an app: the action
creates the user when the instance does not know them (the answer then
carries their invite code once — a managed instance mails nothing,
MIB-D30) and gives them `admin` or `user` on the project of the named
environment, replacing any role they held there before. Audited on every
successful call, like the Git read-token mint.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `email` *required*: `string`
      - description: Email address of the person. One the instance does not know yet is
      - type: `string`
    - `environment` *required*: `string`
      - description: Slug of that project's environment. Each environment has its own
      - type: `string`
    - `project_id` *required*: `integer`
      - description: `projects.id` of a project this Identity service is linked to.
      - type: `integer`
    - `role` *required*: `string`
      - description: A role of a linked Identity project (MIB I5). Apps read it from the
      - type: `string`
- responses:
  - `200`: The role the user holds now, with the invite code of a user created by this call
    - `application/json`:
      - type: `object (5 properties)`
      - `audience` *required*: `string`
        - description: The Zitadel project the role is on: the app's `OIDC_AUDIENCE`.
        - type: `string`
      - `invite_code`: `['string', 'null']`
        - description: The invite code of a person invited by this call, to hand to them
        - type: `['string', 'null']`
      - `invited` *required*: `boolean`
        - description: Whether this call created the user.
        - type: `boolean`
      - `role` *required*: `string`
        - description: A role of a linked Identity project (MIB I5). Apps read it from the
        - type: `string`
      - `user_id` *required*: `string`
        - description: The Zitadel user that holds it; it is the `sub` of their tokens.
        - type: `string`
  - `400`: The service is not an identity service, the project has no environment of that name, or that environment has no identity project yet: deploy it once after linking
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not one this service may grant on
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/invitations`

- operationId: `invite_identity_user`
- summary: Ask the provider to invite a person by verified email delivery. Returns
no acceptance code; access needs the person's verification and a grant
on their provider subject.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `email` *required*: `string`
      - description: Delivery address. The provider sends the verification; the platform
      - type: `string`
    - `environment` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
- responses:
  - `202`: Invitation sent; pending the person's verification
    - `application/json`:
      - type: `object (3 properties)`
      - `invitation_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - description: Always `pending_verification`: access starts only after the person
        - type: `string`
      - `subject`: `['string', 'null']`
        - description: The provider subject, when the provider already assigned one.
        - type: `['string', 'null']`
  - `400`: Invalid address or unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it
  - `409`: The provider does not support verified invitations
  - `503`: The identity provider is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/management`

- operationId: `get_identity_management`
- summary: Service setup, linked applications and supported operations of a managed
identity service (BA4). Readable by every member of the workspace; it
lists no person and no secret.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Provider capabilities and linked applications
    - `application/json`:
      - type: `object (6 properties)`
      - `applications` *required*: `array<object (12 properties)>`
        - type: `array<object (12 properties)>`
      - `capabilities` *required*: `object (15 properties)`
        - type: `object (15 properties)`
      - `operations` *required*: `object (7 properties)`
        - description: Which controls the console enables, derived from the provider's declared
        - type: `object (7 properties)`
      - `provider_label` *required*: `string`
        - description: Provider name for the console label.
        - type: `string`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `service_type` *required*: `string`
        - type: `string`
  - `400`: The service is not an identity provider
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:read)
  - `404`: No such service in this workspace
  - `503`: The identity service is not configured yet

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/management-token/rotate`

- operationId: `rotate_identity_management_token`
- summary: Replace the Better Auth management token and restart the runtime; it
re-keys its management identity. Client ids, subjects, signing keys and
people's sessions are unchanged.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Rotated and the runtime restarted
    - `application/json`:
      - type: `object (1 properties)`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace
  - `409`: The provider has no rotatable management token
  - `503`: The service is not ready

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations`

- operationId: `list_identity_migrations`
- summary: The switches of one linked environment of this service, newest first.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
  - `environment` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Switches of the environment
    - `application/json`:
      - type: `object (1 properties)`
      - `migrations` *required*: `array<object (22 properties)>`
        - type: `array<object (22 properties)>`
  - `400`: Unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: No such service in this workspace, or the project is not linked to it

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations`

- operationId: `create_identity_migration`
- summary: Open a switch of the environment's active identity link (`{id}`) to
another identity service. Nothing the app receives changes.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `environment` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `target_service_id` *required*: `integer`
      - description: Another identity service of this workspace.
      - type: `integer`
- responses:
  - `201`: Switch opened in draft
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `400`: Unknown environment, or a target that is not an identity service
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it
  - `409`: An open switch exists, or the service is not the active link

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}`

- operationId: `get_identity_migration`
- summary: One switch of this service (as source or target).
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The switch
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: No such switch of this service

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/bundle`

- operationId: `get_identity_migration_bundle`
- summary: The verified mapping bundle the app applies.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The mapping bundle
    - `application/json`:
      - type: `object (6 properties)`
      - `digest` *required*: `string`
        - type: `string`
      - `format` *required*: `string`
        - type: `string`
      - `mappings` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `migration_id` *required*: `integer`
        - type: `integer`
      - `source` *required*: `object (2 properties)`
        - type: `object (2 properties)`
      - `target` *required*: `object (2 properties)`
        - type: `object (2 properties)`
  - `404`: No such switch of this service
  - `409`: The switch has no verified mappings

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/cutover`

- operationId: `cutover_identity_migration`
- summary: Make the target the active link at a new generation. Every app replica
must be redeployed; sessions of earlier generations are then refused.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Active at a new generation
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `404`: No such switch of this service
  - `409`: Not cutover-ready

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/mappings`

- operationId: `import_identity_mappings`
- summary: Import audited source → target subject mappings. A matching email is
never a mapping; each subject maps at most once per switch.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `mappings` *required*: `array<object (2 properties)>`
      - type: `array<object (2 properties)>`
- responses:
  - `200`: Accepted, unchanged and conflicting mappings
    - `application/json`:
      - type: `object (3 properties)`
      - `accepted` *required*: `integer`
        - type: `integer`
      - `conflicts` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `unchanged` *required*: `integer`
        - type: `integer`
  - `400`: Invalid subjects or too many mappings
  - `404`: No such switch of this service
  - `409`: Not possible in the switch's state

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/prepare-cutover`

- operationId: `prepare_identity_cutover`
- summary: Confirm the app applied the bundle; outputs still do not change.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `app_mappings_applied`: `boolean`
      - description: The app runs alias-capable code and applied this switch's bundle.
      - type: `boolean`
- responses:
  - `200`: Cutover ready
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `404`: No such switch of this service
  - `409`: Not verified, or the confirmation is missing

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/retire`

- operationId: `retire_identity_migration`
- summary: After the observation window: disable the former provider's client and
grants for the environment. App records and audit history stay.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Former provider retired for the environment
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `404`: No such switch of this service
  - `409`: Not active

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/rollback`

- operationId: `rollback_identity_migration`
- summary: Select the source again at a new generation, keeping aliases and data.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `accept_unmapped_new_users`: `boolean`
      - description: Proceed although users created since cutover cannot sign in on the
      - type: `boolean`
- responses:
  - `200`: Rolled back at a new generation
    - `application/json`:
      - type: `object (2 properties)`
      - `migration` *required*: `object (22 properties)`
        - type: `object (22 properties)`
      - `users_created_since_cutover` *required*: `array<string>`
        - description: Target subjects (bounded) granted after cutover without a source
        - type: `array<string>`
  - `404`: No such switch of this service
  - `409`: Not active, or users created since cutover are not accepted

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/target`

- operationId: `prepare_identity_migration_target`
- summary: Create the target's client for the environment as a staged link and
record its issuer and audience. Live outputs do not change.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Target ready
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `404`: No such switch of this service
  - `409`: Not possible in the switch's state
  - `503`: The target's client is not applied yet; retry

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/migrations/{migration_id}/verify`

- operationId: `verify_identity_migration`
- summary: Verify the mapping set; a pass records and stages the bundle digest.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `migration_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `accept_partial_cohort`: `boolean`
      - description: Accept that enabled source users without a mapping (or an unknown
      - type: `boolean`
- responses:
  - `200`: Verified, or blocked with a reason
    - `application/json`:
      - type: `object (22 properties)`
      - `blocked_reason`: `['string', 'null']`
        - type: `['string', 'null']`
      - `conflict_count` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `cutover_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `cutover_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `mapped_count` *required*: `integer`
        - type: `integer`
      - `mapping_digest`: `['string', 'null']`
        - description: SHA-256 of the verified mapping bundle; staged to the app as
        - type: `['string', 'null']`
      - `partial_cohort` *required*: `boolean`
        - type: `boolean`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `redeploy_required` *required*: `boolean`
        - description: A cutover or rollback takes effect when the app is redeployed with
        - type: `boolean`
      - `retired_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `rollback_generation`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rolled_back_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_generation` *required*: `integer`
        - type: `integer`
      - `source_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `source_service_id` *required*: `integer`
        - type: `integer`
      - `state` *required*: `string`
        - description: `draft`, `target_ready`, `mappings_verified`, `cutover_ready`,
        - type: `string`
      - `target_issuer`: `['string', 'null']`
        - type: `['string', 'null']`
      - `target_service_id` *required*: `integer`
        - type: `integer`
      - `unmapped_count`: `['integer', 'null']`
        - description: `null`: the source cannot list its users, completeness is unknown.
        - type: `['integer', 'null']`
  - `404`: No such switch of this service
  - `409`: Not possible in the switch's state
  - `503`: A provider's users could not be listed; retry

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/operations`

- operationId: `get_identity_operation`
- summary: Progress of one durable identity operation of this service, for the
console's pending/retry state.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `operation_id` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The operation's progress
    - `application/json`:
      - type: `object (4 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `last_attempt_failed` *required*: `boolean`
        - description: The last attempt failed; the reason stays in the server log.
        - type: `boolean`
      - `next_attempt_at`: `['string', 'null']`
        - description: RFC 3339 time of the next retry while not applied.
        - type: `['string', 'null']`
      - `receipt` *required*: `object (4 properties)`
        - description: Progress of one durable operation. `applied` only once the provider
        - type: `object (4 properties)`
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or no such operation of it

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/people/{subject}/erase`

- operationId: `erase_identity_person`
- summary: Erase one person: their account with everything of theirs in the provider,
on every link of this service, then the platform's rows of them. It cannot
be undone, and a restored backup is erased again. `202` once accepted;
`status` says whether the provider has confirmed. A subject neither side
knows is 404 and changes nothing.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `subject` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `environment` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
- responses:
  - `202`: Accepted; `applied` once the provider confirmed
    - `application/json`:
      - type: `object (2 properties)`
      - `operation_id` *required*: `string`
        - description: Follow it at `GET …/identity/operations`. Never names the subject.
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Invalid subject or unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, the project is not linked to it, or no such person
  - `409`: The provider does not support this (identity-user-deletion-unsupported)
  - `503`: The identity provider is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/people/{subject}/export`

- operationId: `export_identity_person`
- summary: What the provider holds about one person: their account, sessions, passkeys
and every link's grants and admissions. Workspace Admin only, and it is
personal data: the answer is `no-store` and the platform keeps none of it.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `subject` (path) *required*: `string`
  - `project_id` (query) *required*: `integer`
  - `environment` (query) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The person's account data
    - `application/json`:
      - type: `object (9 properties)`
      - `admissions` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `created_at` *required*: `string`
        - description: RFC 3339.
        - type: `string`
      - `email` *required*: `string`
        - type: `string`
      - `email_verified` *required*: `boolean`
        - type: `boolean`
      - `grants` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `name` *required*: `string`
        - type: `string`
      - `passkeys` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `sessions` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `subject` *required*: `string`
        - description: Opaque provider subject.
        - type: `string`
  - `400`: Invalid subject or unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, the project is not linked to it, or no such person
  - `409`: The provider does not support this (identity-user-deletion-unsupported)
  - `503`: The identity provider is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/restore/quarantine`

- operationId: `quarantine_restored_identity`
- summary: Restart a service whose identity database was restored in quarantine:
no public sign-in or issuance and no positive resource status.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Quarantined
    - `application/json`:
      - type: `object (1 properties)`
      - `status` *required*: `string`
        - type: `string`
  - `404`: No such service in this workspace
  - `409`: The provider does not support restore quarantine

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/restore/reconcile`

- operationId: `reconcile_restored_identity`
- summary: Apply the platform's durable denials to the quarantined runtime, end
every restored session and grant, then leave quarantine.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Reconciled and released from quarantine
    - `application/json`:
      - type: `object (8 properties)`
      - `denied_grants` *required*: `integer`
        - type: `integer`
      - `disabled_applications` *required*: `integer`
        - type: `integer`
      - `erased_subjects` *required*: `integer`
        - description: The people deleted from the restored snapshot. Required: a runtime that
        - type: `integer`
      - `reconciled_at` *required*: `string`
        - description: RFC 3339.
        - type: `string`
      - `removed_verifications` *required*: `integer`
        - type: `integer`
      - `revoked_access_tokens` *required*: `integer`
        - type: `integer`
      - `revoked_refresh_tokens` *required*: `integer`
        - type: `integer`
      - `revoked_sessions` *required*: `integer`
        - type: `integer`
  - `404`: No such service in this workspace
  - `409`: The provider does not support restore reconciliation
  - `503`: The runtime could not be reconciled; it stays quarantined

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/session-revocations`

- operationId: `revoke_identity_sessions`
- summary: Durably revoke one subject's identity-provider sessions. This ends their
provider login and active tokens; app sessions end at the app's next
resource-status check. `200` once applied, `202` while pending.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `environment` *required*: `string`
      - type: `string`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `subject` *required*: `string`
      - description: Opaque provider subject.
      - type: `string`
- responses:
  - `200`: Applied by the provider
    - `application/json`:
      - type: `object (4 properties)`
      - `applied_revision` *required*: `integer`
        - type: `integer`
      - `desired_revision` *required*: `integer`
        - type: `integer`
      - `operation_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `202`: Recorded; the provider has not acknowledged it yet
    - `application/json`:
      - type: `object (4 properties)`
      - `applied_revision` *required*: `integer`
        - type: `integer`
      - `desired_revision` *required*: `integer`
        - type: `integer`
      - `operation_id` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Invalid subject or unknown environment
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it
  - `409`: The provider does not support session revocation

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/signing-keys/rotate`

- operationId: `rotate_identity_signing_keys`
- summary: End the live signing keys now; tokens they signed keep verifying for the
provider's grace period.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Live keys retired
    - `application/json`:
      - type: `object (2 properties)`
      - `retired_keys` *required*: `integer`
        - type: `integer`
      - `rotated_at` *required*: `string`
        - description: RFC 3339.
        - type: `string`
  - `404`: No such service in this workspace
  - `409`: The provider does not rotate signing keys on request
  - `503`: The provider is unavailable

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/identity/users`

- operationId: `list_identity_users`
- summary: One redacted page of the provider's users: opaque subject, verification
and disabled flags only. Workspace Admin only.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (query) *required*: `integer`
  - `environment` (query) *required*: `string`
  - `cursor` (query): `string`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: One page of redacted users
    - `application/json`:
      - type: `object (2 properties)`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
      - `users` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `400`: Unknown environment, bad cursor or limit
  - `401`: Unauthorized
  - `403`: Insufficient permissions (requires services:write and the workspace role Admin)
  - `404`: No such service in this workspace, or the project is not linked to it
  - `409`: The provider does not support listing users
  - `503`: The identity provider is unavailable

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/logs/search`

- operationId: `search_service_logs`
- summary: Search a managed service's logs.
- description: Managed-service containers are not archived (the collector keeps project
containers only), so this reads the service container's engine log within
the window and filters it like the project search; `search_mode` is
`live` and the lines carry no chunk for `logs/context`.
- tags: `Logs v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (6 properties)`
    - `cursor`: `['string', 'null']`
      - description: `next_cursor` of the previous page: returns strictly older lines.
      - type: `['string', 'null']`
    - `end_time`: `['string', 'null']`
      - description: End of the window (RFC 3339). Defaults to now.
      - type: `['string', 'null']`
    - `levels`: `array<string>`
      - type: `array<string>`
    - `page_size`: `['integer', 'null']`
      - description: Lines per page (default 100, at most 2000).
      - type: `['integer', 'null']`
    - `start_time`: `['string', 'null']`
      - description: Start of the window (RFC 3339). Defaults to one hour before `end_time`.
      - type: `['string', 'null']`
    - `text`: `['string', 'null']`
      - description: Case-insensitive substring of the message.
      - type: `['string', 'null']`
- responses:
  - `200`: Search results
    - `application/json`:
      - type: `object (5 properties)`
      - `available_sources`: `array<object (4 properties)>`
        - description: Distinct containers/nodes/services available in the queried scope, for
        - type: `array<object (4 properties)>`
      - `lines` *required*: `array<object (14 properties)>`
        - type: `array<object (14 properties)>`
      - `next_cursor`: `['string', 'null']`
        - type: `['string', 'null']`
      - `search_mode` *required*: `string`
        - description: Search execution mode
        - type: `string`
      - `total_scanned` *required*: `integer`
        - type: `integer`
  - `400`: Invalid search parameters
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Missing logs:read or services:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No such service in this workspace
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: `urn:conusai:logs:service-on-worker-node`: the service runs on a worker node
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: `urn:conusai:logs:service-logs-unavailable`: no container log source on this install
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/members`

- operationId: `add_cluster_member`
- summary: Add a member to a running cluster.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `node_id`: `['integer', 'null']`
      - description: Target worker node ID. Omit or null to run on the control plane.
      - type: `['integer', 'null']`
    - `role` *required*: `string`
      - description: Member role. Currently only `replica` is accepted at runtime —
      - type: `string`
- responses:
  - `202`: Cluster member provisioning started
    - `application/json`:
      - type: `object (12 properties)`
      - `compute_ip`: `['string', 'null']`
        - description: Container's IP on the `conusai-overlay` multi-host network. Populated
        - type: `['string', 'null']`
      - `container_name` *required*: `string`
        - type: `string`
      - `hostname`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `live_state`: `['string', 'null']`
        - description: Live FSM state from the `pg_auto_failover` monitor (`primary`,
        - type: `['string', 'null']`
      - `node_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `ordinal` *required*: `integer`
        - type: `integer`
      - `port`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `provisioning_error`: `['string', 'null']`
        - description: Most recent provisioning failure message, when `status='failed'`.
        - type: `['string', 'null']`
      - `provisioning_step`: `['string', 'null']`
        - description: Last-attempted phase of the async `add_cluster_member` background
        - type: `['string', 'null']`
      - `role` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/members/{member_id}`

- operationId: `get_cluster_member`
- summary: Read one cluster member.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `member_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cluster member details
    - `application/json`:
      - type: `object (12 properties)`
      - `compute_ip`: `['string', 'null']`
        - description: Container's IP on the `conusai-overlay` multi-host network. Populated
        - type: `['string', 'null']`
      - `container_name` *required*: `string`
        - type: `string`
      - `hostname`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `live_state`: `['string', 'null']`
        - description: Live FSM state from the `pg_auto_failover` monitor (`primary`,
        - type: `['string', 'null']`
      - `node_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `ordinal` *required*: `integer`
        - type: `integer`
      - `port`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `provisioning_error`: `['string', 'null']`
        - description: Most recent provisioning failure message, when `status='failed'`.
        - type: `['string', 'null']`
      - `provisioning_step`: `['string', 'null']`
        - description: Last-attempted phase of the async `add_cluster_member` background
        - type: `['string', 'null']`
      - `role` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or member not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/members/{member_id}`

- operationId: `remove_cluster_member`
- summary: Remove one member from a running cluster.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `member_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Cluster member removed
  - `400`: Removal would break quorum, or member is the monitor/primary
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or member not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/members/{member_id}/promote`

- operationId: `promote_cluster_member`
- summary: Promote one cluster member to primary.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `member_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Promotion initiated
  - `400`: Validation failed (monitor, already primary, not running, etc.)
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or member not found in this workspace
  - `500`: Promotion failed

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics`

- operationId: `get_service_metrics_range`
- summary: Time-series range for one metric on one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `metric` (query) *required*: `string`
  - `range` (query): `string`
  - `percentile` (query): `['number', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Metric time series data points
    - `application/json`:
      - type: `array<object (2 properties)>`
  - `400`: Invalid query parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `503`: Metrics store not available

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/alert-rules`

- operationId: `list_service_alert_rules`
- summary: List the alert rules of one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of alert rules
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/alert-rules`

- operationId: `create_service_alert_rule`
- summary: Create an alert rule on one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `comparator` *required*: `string`
      - description: One of `>`, `<`, `>=`, `<=`.
      - type: `string`
    - `enabled`: `boolean`
      - type: `boolean`
    - `for_duration_secs`: `integer`
      - description: Seconds the breach must persist before the alarm fires (0 = immediate).
      - type: `integer`
    - `metric_name` *required*: `string`
      - type: `string`
    - `name` *required*: `string`
      - type: `string`
    - `severity` *required*: `string`
      - description: `"warning"` or `"critical"`.
      - type: `string`
    - `threshold` *required*: `number`
      - type: `number`
- responses:
  - `201`: Alert rule created
    - `application/json`:
      - type: `object (11 properties)`
      - `comparator` *required*: `string`
        - type: `string`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `for_duration_secs` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `metric_name` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `severity` *required*: `string`
        - type: `string`
      - `silenced_until`: `['string', 'null']`
        - type: `['string', 'null']`
      - `threshold` *required*: `number`
        - type: `number`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `PUT /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/alert-rules/{rule_id}`

- operationId: `update_service_alert_rule`
- summary: Update one alert rule of one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `rule_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (7 properties)`
    - `comparator`: `['string', 'null']`
      - type: `['string', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `for_duration_secs`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `metric_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `severity`: `['string', 'null']`
      - type: `['string', 'null']`
    - `threshold`: `['number', 'null']`
      - type: `['number', 'null']`
- responses:
  - `200`: Updated alert rule
    - `application/json`:
      - type: `object (11 properties)`
      - `comparator` *required*: `string`
        - type: `string`
      - `deployment_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `for_duration_secs` *required*: `integer`
        - type: `integer`
      - `id` *required*: `integer`
        - type: `integer`
      - `metric_name` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - type: `string`
      - `service_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `severity` *required*: `string`
        - type: `string`
      - `silenced_until`: `['string', 'null']`
        - type: `['string', 'null']`
      - `threshold` *required*: `number`
        - type: `number`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or alert rule not found in this workspace
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/alert-rules/{rule_id}`

- operationId: `delete_service_alert_rule`
- summary: Delete one alert rule of one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `rule_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Alert rule deleted
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or alert rule not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/by-database`

- operationId: `get_service_metrics_by_database`
- summary: Per-database metric breakdown for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Per-database metric breakdown
    - `application/json`:
      - type: `object (1 properties)`
      - `databases` *required*: `array<object (2 properties)>`
        - description: One entry per database, sorted by the first metric descending
        - type: `array<object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/enable`

- operationId: `toggle_service_metrics`
- summary: Turn metric collection on or off for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `enabled` *required*: `boolean`
      - description: Whether to enable (`true`) or disable (`false`) metric collection.
      - type: `boolean`
- responses:
  - `200`: Metrics toggle applied
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/latest`

- operationId: `get_service_metrics_latest`
- summary: Latest metric values for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Map of metric name to latest value
    - `application/json`:
      - type: `object`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `503`: Metrics store not available

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/metrics/status`

- operationId: `get_service_metrics_status`
- summary: Metrics freshness status for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Metrics freshness status
    - `application/json`:
      - type: `object (1 properties)`
      - `last_received_at`: `['string', 'null']`
        - description: ISO 8601 timestamp of the most recent metric row, or null if none yet.
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/preview-environment-masked`

- operationId: `get_service_preview_environment_variables_masked`
- summary: Preview of a service's environment variables with sensitive values masked.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Environment variables with sensitive values masked
    - `application/json`:
      - type: `object`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/projects`

- operationId: `list_service_projects`
- summary: List the projects one managed service is linked to.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: List of linked projects
    - `application/json`:
      - type: `array<object (4 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/projects`

- operationId: `link_service_to_project`
- summary: Link one managed service to a project.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `project_id` *required*: `integer`
      - type: `integer`
    - `role`: `['string', 'null']`
      - description: The link's role: which of the project's links of this service type it
      - type: `['string', 'null']`
- responses:
  - `201`: Service linked to project
    - `application/json`:
      - type: `object (4 properties)`
      - `id` *required*: `integer`
        - type: `integer`
      - `project` *required*: `object (3 properties)`
        - type: `object (3 properties)`
      - `role` *required*: `string`
        - description: The link's role (`default` unless one was named when linking); it
        - type: `string`
      - `service` *required*: `object (13 properties)`
        - type: `object (13 properties)`
  - `400`: The role is unknown or not available for this service type
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or project not found in this workspace
  - `409`: Project already has a linked service of this type and role, or this service is already linked to it
  - `500`: Internal server error

### `DELETE /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/projects/{project_id}`

- operationId: `unlink_service_from_project`
- summary: Unlink one managed service from a project.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Service unlinked from project
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service link not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/projects/{project_id}/environment`

- operationId: `get_service_environment_variables`
- summary: List the environment variables one service exposes to one project.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of environment variables
    - `application/json`:
      - type: `array<object (3 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or project not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/projects/{project_id}/environment/{var_name}`

- operationId: `get_service_environment_variable`
- summary: Read one environment variable a service exposes to a project.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `project_id` (path) *required*: `integer`
  - `var_name` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Environment variable value
    - `application/json`:
      - type: `object (3 properties)`
      - `name` *required*: `string`
        - type: `string`
      - `sensitive` *required*: `boolean`
        - description: Whether this variable contains sensitive data (passwords, keys, tokens)
        - type: `boolean`
      - `value` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: A sensitive variable needs an admin; in a browser session, a fresh step-up
  - `404`: Service, project or variable not found in this workspace
  - `500`: Internal server error

### `PATCH /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/resources`

- operationId: `update_service_resources`
- summary: Update one managed service's CPU and memory limits.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (8 properties)`
    - `cpu_request_nano_cpus`: `['integer', 'null']`
      - description: CPU request in nano-cpus (`1_000_000_000` = one core): the service's
      - type: `['integer', 'null']`
    - `cpu_shares`: `['integer', 'null']`
      - description: Relative CPU weight (default 1024). Only used when `nano_cpus` is None.
      - type: `['integer', 'null']`
    - `memory_mb`: `['integer', 'null']`
      - description: Hard memory limit in MiB. None = unlimited.
      - type: `['integer', 'null']`
    - `memory_request_mb`: `['integer', 'null']`
      - description: Memory request (soft limit) in MiB: what the service is guaranteed
      - type: `['integer', 'null']`
    - `memory_swap_mb`: `['integer', 'null']`
      - description: Memory + swap limit in MiB. None = unlimited.
      - type: `['integer', 'null']`
    - `nano_cpus`: `['integer', 'null']`
      - description: CPU quota in nano-cpus. `1_000_000_000` = 1 full CPU core. None = unlimited.
      - type: `['integer', 'null']`
    - `shm_size_mb`: `['integer', 'null']`
      - description: Shared memory (/dev/shm) size in MiB. None = Docker default (64 MiB).
      - type: `['integer', 'null']`
    - `unlimited`: `boolean`
      - description: The operator's explicit opt-out of the engine's default memory cap.
      - type: `boolean`
- responses:
  - `200`: Updated resource limits
    - `application/json`:
      - type: `object (2 properties)`
      - `applied` *required*: `array<object (4 properties)>`
        - description: Per-container result of trying to apply the limits live.
        - type: `array<object (4 properties)>`
      - `limits` *required*: `object (8 properties)`
        - description: Optional cgroup resource limits applied to a service container.
        - type: `object (8 properties)`
  - `400`: Invalid resource limits
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/retry`

- operationId: `retry_cluster`
- summary: Retry a failed cluster provisioning run.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `members`: `array<object (2 properties)>`
      - description: Cluster member specifications (same format as create).
      - type: `array<object (2 properties)>`
- responses:
  - `200`: Cluster retry initiated
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/runtime`

- operationId: `get_service_runtime`
- summary: Container runtime snapshot for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Container runtime snapshot
    - `application/json`:
      - type: `object (3 properties)`
      - `members` *required*: `array<object (11 properties)>`
        - type: `array<object (11 properties)>`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `topology` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/start`

- operationId: `start_service`
- summary: Start one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Service started
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `409`: A Postgres major upgrade is in progress for this service
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/stats`

- operationId: `get_service_stats`
- summary: Container stats snapshot for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Container stats snapshot
    - `application/json`:
      - type: `object (3 properties)`
      - `members` *required*: `array<object (7 properties)>`
        - type: `array<object (7 properties)>`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `topology` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/stop`

- operationId: `stop_service`
- summary: Stop one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Service stopped
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/upgrade`

- operationId: `upgrade_service`
- summary: Upgrade one managed service to a new version.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `docker_image` *required*: `string`
      - description: Docker image to upgrade to (e.g., "build.conusai.com/conusai/postgres-walg:18-bookworm")
      - type: `string`
- responses:
  - `200`: Service upgraded
    - `application/json`:
      - type: `object (13 properties)`
      - `connection_info`: `['string', 'null']`
        - type: `['string', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - description: Error message from failed initialization.
        - type: `['string', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `members`: `array<object (12 properties)>`
        - description: Cluster members (empty for standalone services).
        - type: `array<object (12 properties)>`
      - `metrics_enabled`: `boolean`
        - description: Whether metric collection is enabled for this service. The UI uses this
        - type: `boolean`
      - `name` *required*: `string`
        - type: `string`
      - `node_id`: `['integer', 'null']`
        - description: Node ID where the service runs. Null means control plane (local).
        - type: `['integer', 'null']`
      - `service_type` *required*: `string`
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `topology` *required*: `string`
        - description: Service topology: "standalone" (single container) or "cluster" (HA multi-member).
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
      - `version`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{id}/wal-health`

- operationId: `get_postgres_wal_health`
- summary: Latest write-ahead-log health snapshot for a Postgres service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Latest WAL health snapshot
    - `application/json`:
      - type: `object (11 properties)`
      - `archive_backlog` *required*: `integer`
        - description: Number of `archive_status/*.ready` files — un-shipped WAL segments.
        - type: `integer`
      - `archive_command`: `['string', 'null']`
        - description: The literal `archive_command` setting. May be empty or `/bin/true`
        - type: `['string', 'null']`
      - `archive_mode` *required*: `string`
        - type: `string`
      - `archiver_failed_count`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `archiver_last_failed_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `max_wal_size_bytes` *required*: `integer`
        - description: `max_wal_size` setting in bytes (parsed from `pg_settings`).
        - type: `integer`
      - `oldest_wal_age_secs` *required*: `integer`
        - description: Age of the oldest WAL file in `pg_wal/` (seconds).
        - type: `integer`
      - `pg_wal_bytes` *required*: `integer`
        - description: Total size of files under `pg_wal/`, from `pg_ls_waldir()`.
        - type: `integer`
      - `probed_at` *required*: `string`
        - description: When the snapshot was taken.
        - type: `string`
      - `stale_slots` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `warnings` *required*: `array<object (4 properties) | object (4 properties) | object (2 properties) | object (1 properties) | object (2 properties)>`
        - description: Computed warnings, ordered by severity (critical first).
        - type: `array<object (4 properties) | object (4 properties) | object (2 properties) | object (1 properties) | object (2 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/pg-stat-statements/enable`

- operationId: `enable_pg_stat_statements`
- summary: Enable `pg_stat_statements` on one standalone Postgres service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Container recreated; pg_stat_statements now active
    - `application/json`:
      - type: `object (1 properties)`
      - `message` *required*: `string`
        - description: Human-readable message confirming the action.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `422`: Service is not standalone Postgres
  - `500`: Restart failed

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/pg-stat-statements/slow-queries`

- operationId: `get_slow_queries`
- summary: Paginated `pg_stat_statements` slow queries for one managed service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `page` (query): `['integer', 'null']`
  - `page_size` (query): `['integer', 'null']`
  - `sort_by` (query): `['string', 'null']`
  - `sort_order` (query): `['string', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Paginated slow queries from pg_stat_statements
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - description: Current page number (1-based).
        - type: `integer`
      - `page_size` *required*: `integer`
        - description: Number of rows per page used for this request.
        - type: `integer`
      - `queries` *required*: `array<object (7 properties)>`
        - description: Ordered list of query stats, slowest first by `mean_exec_time_ms`
        - type: `array<object (7 properties)>`
      - `total_count` *required*: `integer`
        - description: Total number of qualifying rows across all pages.
        - type: `integer`
  - `400`: Invalid pagination parameters
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `422`: Service is not a Postgres service
  - `502`: Could not reach the target Postgres
  - `503`: pg_stat_statements extension not available

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers`

- operationId: `list_root_containers`
- summary: List the root containers (databases, buckets) of one service.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: List of root containers
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}`

- operationId: `list_containers_at_path`
- summary: List the containers nested at one path.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: List of containers
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}/entities`

- operationId: `list_entities`
- summary: List the entities (tables, collections, objects) in one container.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
  - `limit` (query): `integer`
  - `token` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Paginated list of entities
    - `application/json`:
      - type: `object (6 properties)`
      - `count` *required*: `integer`
        - description: Number of entities returned
        - type: `integer`
      - `entities` *required*: `array<object (4 properties)>`
        - description: List of entities
        - type: `array<object (4 properties)>`
      - `has_more` *required*: `boolean`
        - description: Whether there are more entities available
        - type: `boolean`
      - `limit` *required*: `integer`
        - description: Limit used for this request
        - type: `integer`
      - `next_token`: `['string', 'null']`
        - description: Continuation token for next page (S3, etc.)
        - type: `['string', 'null']`
      - `total`: `['integer', 'null']`
        - description: Total number of entities (if available)
        - type: `['integer', 'null']`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}/entities/{entity}`

- operationId: `get_entity_info`
- summary: Read one entity's schema and metadata.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
  - `entity` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Entity details
    - `application/json`:
      - type: `object (8 properties)`
      - `container_path` *required*: `array<string>`
        - description: Full container path
        - type: `array<string>`
      - `entity` *required*: `string`
        - description: Entity name
        - type: `string`
      - `entity_type` *required*: `string`
        - description: Entity type
        - type: `string`
      - `fields` *required*: `array<object (3 properties)>`
        - description: Field definitions
        - type: `array<object (3 properties)>`
      - `metadata`: `any`
        - description: Additional metadata (`content_type`, `last_modified`, etag, etc.)
        - type: `any`
      - `row_count`: `['integer', 'null']`
        - description: Approximate row count (for tables/collections)
        - type: `['integer', 'null']`
      - `size_bytes`: `['integer', 'null']`
        - description: Size in bytes (for objects/files)
        - type: `['integer', 'null']`
      - `sort_schema`: `any`
        - description: JSON Schema for sort options (if supported)
        - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or entity not found in this workspace
  - `500`: Internal server error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}/entities/{entity}/data`

- operationId: `query_data`
- summary: Query the rows of one entity.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
  - `entity` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `filters`: `any`
      - description: JSON filters (backend-specific format)
      - type: `any`
    - `limit`: `integer`
      - description: Maximum number of rows to return (default 100). Values above
      - type: `integer`
    - `offset`: `integer`
      - description: Number of rows to skip
      - type: `integer`
    - `sort_by`: `['string', 'null']`
      - description: Sort by field name
      - type: `['string', 'null']`
    - `sort_order`: `['string', 'null']`
      - description: Sort order (asc/desc)
      - type: `['string', 'null']`
- responses:
  - `200`: Query results
    - `application/json`:
      - type: `object (5 properties)`
      - `execution_time_ms` *required*: `integer`
        - description: Query execution time in milliseconds
        - type: `integer`
      - `fields` *required*: `array<object (3 properties)>`
        - description: Field definitions
        - type: `array<object (3 properties)>`
      - `returned_count` *required*: `integer`
        - description: Number of rows returned in this response
        - type: `integer`
      - `rows` *required*: `array<any>`
        - description: Data rows (array of JSON objects)
        - type: `array<any>`
      - `total_count` *required*: `integer`
        - description: Total number of rows matching the query (before limit/offset)
        - type: `integer`
  - `400`: Invalid query
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or entity not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}/entities/{entity}/download`

- operationId: `download_object`
- summary: Stream one stored object back to the caller.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
  - `entity` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Object data stream
    - `application/octet-stream`:
      - type: `any`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or object not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/containers/{path}/info`

- operationId: `get_container_info`
- summary: Read one container's metadata.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Container information
    - `application/json`:
      - type: `object (8 properties)`
      - `can_contain_containers` *required*: `boolean`
        - description: Can this container hold other containers?
        - type: `boolean`
      - `can_contain_entities` *required*: `boolean`
        - description: Can this container hold entities (tables, collections, etc.)?
        - type: `boolean`
      - `child_container_type`: `['string', 'null']`
        - description: Type of child containers (if `can_contain_containers` is true)
        - type: `['string', 'null']`
      - `container_type` *required*: `string`
        - description: Container type (database, schema, keyspace, bucket, etc.)
        - type: `string`
      - `entity_count_hint`: `['string', 'null']`
        - description: Hint for UI on expected entity count (small = sidebar, large = pagination)
        - type: `['string', 'null']`
      - `entity_type_label`: `['string', 'null']`
        - description: Label for entity type (if `can_contain_entities` is true)
        - type: `['string', 'null']`
      - `metadata` *required*: `any`
        - description: Additional metadata
        - type: `any`
      - `name` *required*: `string`
        - description: Container name
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service or container not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/query/explorer-support`

- operationId: `check_explorer_support`
- summary: Whether the data explorer supports this service type.
- tags: `Services v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Explorer support information
    - `application/json`:
      - type: `object (6 properties)`
      - `capabilities` *required*: `array<string>`
        - description: Capabilities supported by this service
        - type: `array<string>`
      - `filter_schema`: `any`
        - description: JSON Schema for filter format with embedded UI hints (if supported)
        - type: `any`
      - `hierarchy` *required*: `array<object (5 properties)>`
        - description: Hierarchy levels (describes the navigation structure)
        - type: `array<object (5 properties)>`
      - `reason`: `['string', 'null']`
        - description: Reason why explorer is not supported (if applicable)
        - type: `['string', 'null']`
      - `service_type` *required*: `string`
        - description: Service type
        - type: `string`
      - `supported` *required*: `boolean`
        - description: Whether the service supports query explorer functionality
        - type: `boolean`
  - `401`: Unauthorized
  - `403`: Insufficient permissions
  - `404`: Service not found in this workspace
  - `500`: Internal server error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades`

- operationId: `list_pg_upgrades_in_workspace`
- summary: List recent upgrades for a service, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Recent upgrades
    - `application/json`:
      - type: `array<object (16 properties)>`
  - `401`: Unauthorized
  - `404`: Service not found in this workspace
  - `500`: Internal error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades`

- operationId: `start_pg_upgrade_in_workspace`
- summary: Start a new `PostgreSQL` major-version upgrade, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `from_image` *required*: `string`
      - type: `string`
    - `from_version` *required*: `string`
      - type: `string`
    - `to_image` *required*: `string`
      - type: `string`
    - `to_version` *required*: `string`
      - type: `string`
- responses:
  - `201`: Upgrade started
    - `application/json`:
      - type: `object (16 properties)`
      - `attempt` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `from_image` *required*: `string`
        - type: `string`
      - `from_version` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `log_id` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `pre_upgrade_backup_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rollback_volume_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `to_image` *required*: `string`
        - type: `string`
      - `to_version` *required*: `string`
        - type: `string`
  - `400`: Invalid request
  - `401`: Unauthorized
  - `404`: Service not found in this workspace
  - `409`: An upgrade is already running for this service
  - `412`: No default S3 source configured
  - `500`: Internal error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades/{id}`

- operationId: `get_pg_upgrade_in_workspace`
- summary: Get a single upgrade, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Upgrade
    - `application/json`:
      - type: `object (16 properties)`
      - `attempt` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `from_image` *required*: `string`
        - type: `string`
      - `from_version` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `log_id` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `pre_upgrade_backup_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rollback_volume_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `to_image` *required*: `string`
        - type: `string`
      - `to_version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Service or upgrade not found in this workspace
  - `500`: Internal error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades/{id}/cancel`

- operationId: `cancel_pg_upgrade_in_workspace`
- summary: Cancel an in-flight upgrade, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Cancellation requested
    - `application/json`:
      - type: `object (16 properties)`
      - `attempt` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `from_image` *required*: `string`
        - type: `string`
      - `from_version` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `log_id` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `pre_upgrade_backup_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rollback_volume_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `to_image` *required*: `string`
        - type: `string`
      - `to_version` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Service or upgrade not found in this workspace
  - `409`: Upgrade already terminal
  - `500`: Internal error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades/{id}/logs`

- operationId: `get_pg_upgrade_logs_in_workspace`
- summary: Get accumulated log content for an upgrade, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Log content
    - `application/json`:
      - type: `object (2 properties)`
      - `content` *required*: `string`
        - type: `string`
      - `log_id` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
  - `404`: Service or upgrade not found in this workspace
  - `500`: Internal error

### `POST /v1/orgs/{org_slug}/workspaces/{workspace_slug}/services/{service_id}/upgrades/{id}/retry`

- operationId: `retry_pg_upgrade_in_workspace`
- summary: Retry a failed upgrade, in a path-scoped workspace.
- tags: `Postgres Upgrades v1`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `service_id` (path) *required*: `integer`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Retry scheduled
    - `application/json`:
      - type: `object (16 properties)`
      - `attempt` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `error_message`: `['string', 'null']`
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `from_image` *required*: `string`
        - type: `string`
      - `from_version` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `log_id` *required*: `string`
        - type: `string`
      - `phase` *required*: `string`
        - type: `string`
      - `pre_upgrade_backup_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `rollback_volume_name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `service_id` *required*: `integer`
        - type: `integer`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - type: `string`
      - `to_image` *required*: `string`
        - type: `string`
      - `to_version` *required*: `string`
        - type: `string`
  - `400`: Upgrade is not in a retriable state
  - `401`: Unauthorized
  - `404`: Service or upgrade not found in this workspace
  - `500`: Internal error

### `GET /v1/orgs/{org_slug}/workspaces/{workspace_slug}/{name}/{path}`

- operationId: `workspace_service_route`
- summary: A request for a workspace-level service:
`/v1/orgs/{org_slug}/workspaces/{workspace_slug}/{name}/…`.
- tags: `Service gateway`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `workspace_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization's plan does not include the service
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The licence is degraded, or the service is not rolled out to this organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The workspace does not exist or the caller cannot see it; (`type` `urn:conusai:service:not-enabled`) the service is not installed or not enabled; or no such route
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: (`type` `urn:conusai:service:unavailable`) the service runs on a host that cannot be reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org_slug}/{name}/{path}`

- operationId: `org_service_route`
- summary: A request for an organization-level service:
`/v1/orgs/{org_slug}/{name}/…`.
- description: Authenticated like every org route: a caller outside the organization
gets the same `404` as for one that does not exist, before anything about
a service is revealed. Every method is routed here.
- tags: `Service gateway`
- parameters:
  - `org_slug` (path) *required*: `string`
  - `name` (path) *required*: `string`
  - `path` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `401`: No valid credential
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: The organization's plan does not include the service (`error_code` `SERVICE_NOT_ENTITLED`)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The licence is degraded, or the service is not rolled out to this organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The organization does not exist or the caller is not a member; (`type` `urn:conusai:service:not-enabled`, `service`) the service is not installed or not enabled for it; or no such route
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: (`type` `urn:conusai:service:unavailable`) the service is enabled but runs on a host that cannot be reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/support/settings`

- operationId: `get_support_settings`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The organization's support settings
    - `application/json`:
      - type: `object (1 properties)`
      - `default_model`: `['string', 'null']`
        - description: The model a channel with an empty `assistant.model` uses before the
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /v1/orgs/{org}/support/settings`

- operationId: `update_support_settings`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `default_model`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: The settings as stored
    - `application/json`:
      - type: `object (1 properties)`
      - `default_model`: `['string', 'null']`
        - description: The model a channel with an empty `assistant.model` uses before the
        - type: `['string', 'null']`
  - `400`: Invalid model identifier
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels`

- operationId: `list_channels`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Channels of the project
    - `application/json`:
      - type: `array<object (21 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels`

- operationId: `create_channel`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `agent_write_tools`: `['boolean', 'null']`
      - description: Offer agent-approved write tools to the assistant (N-D6). Omitted:
      - type: `['boolean', 'null']`
    - `allowed_origins`: `array<string>`
      - type: `array<string>`
    - `appearance`: `object (4 properties) | null`
      - type: `object (4 properties) | null`
    - `assistant`: `any`
      - type: `any`
    - `data_policy`: `object (10 properties) | null`
      - type: `object (10 properties) | null`
    - `environment_id`: `['integer', 'null']`
      - description: The environment the channel is bound to. Omitted: the project's
      - type: `['integer', 'null']`
    - `identity_keys`: `array<object (5 properties)>`
      - type: `array<object (5 properties)>`
    - `idle_close_days`: `['integer', 'null']`
      - description: Days without a message before an open conversation closes (1 to 365).
      - type: `['integer', 'null']`
    - `name` *required*: `string`
      - type: `string`
    - `offline_policy`: `object (3 properties) | null`
      - type: `object (3 properties) | null`
    - `reply_email_enabled`: `['boolean', 'null']`
      - description: Mail agent replies to contacts with a verified reply address (S3.5a).
      - type: `['boolean', 'null']`
    - `trusted_issuers`: `['array', 'null']`
      - description: Omitted: use managed Identity. `[]`: no OIDC issuer is trusted.
      - type: `['array', 'null']`
- responses:
  - `201`: Channel created; generated HS256 secrets are shown once; `warnings` names saved settings that will not work as configured
    - `application/json`:
      - type: `object (21 properties)`
      - `agent_write_tools` *required*: `boolean`
        - description: N-D6: the assistant may propose the write tools of the channel's
        - type: `boolean`
      - `allowed_origins` *required*: `array<string>`
        - type: `array<string>`
      - `appearance` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `assistant` *required*: `any`
        - type: `any`
      - `assistant_version` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `data_policy` *required*: `object (10 properties)`
        - type: `object (10 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `generated_identity_secrets`: `['array', 'null']`
        - type: `['array', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `identity_keys` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `idle_close_days` *required*: `integer`
        - description: Days without a message after which an open conversation is closed
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `offline_policy` *required*: `object (3 properties)`
        - description: The channel's offline policy (spec §4 queue policy). The team is
        - type: `object (3 properties)`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `public_key` *required*: `string`
        - type: `string`
      - `reply_email_enabled` *required*: `boolean`
        - description: S3.5a (N-D5): an agent's reply is also mailed to a contact who has a
        - type: `boolean`
      - `trusted_issuers`: `['array', 'null']`
        - description: Explicit OIDC trust. `null` uses the environment's managed Identity;
        - type: `['array', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `warnings`: `array<object (5 properties)>`
        - description: Settings that are saved but will not work as configured, worked out
        - type: `array<object (5 properties)>`
  - `400`: Invalid channel settings
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: max_support_channels reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}`

- operationId: `get_channel`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Channel
    - `application/json`:
      - type: `object (21 properties)`
      - `agent_write_tools` *required*: `boolean`
        - description: N-D6: the assistant may propose the write tools of the channel's
        - type: `boolean`
      - `allowed_origins` *required*: `array<string>`
        - type: `array<string>`
      - `appearance` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `assistant` *required*: `any`
        - type: `any`
      - `assistant_version` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `data_policy` *required*: `object (10 properties)`
        - type: `object (10 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `generated_identity_secrets`: `['array', 'null']`
        - type: `['array', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `identity_keys` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `idle_close_days` *required*: `integer`
        - description: Days without a message after which an open conversation is closed
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `offline_policy` *required*: `object (3 properties)`
        - description: The channel's offline policy (spec §4 queue policy). The team is
        - type: `object (3 properties)`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `public_key` *required*: `string`
        - type: `string`
      - `reply_email_enabled` *required*: `boolean`
        - description: S3.5a (N-D5): an agent's reply is also mailed to a contact who has a
        - type: `boolean`
      - `trusted_issuers`: `['array', 'null']`
        - description: Explicit OIDC trust. `null` uses the environment's managed Identity;
        - type: `['array', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `warnings`: `array<object (5 properties)>`
        - description: Settings that are saved but will not work as configured, worked out
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}`

- operationId: `update_channel`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (12 properties)`
    - `agent_write_tools`: `['boolean', 'null']`
      - description: Offer agent-approved write tools to the assistant (N-D6).
      - type: `['boolean', 'null']`
    - `allowed_origins`: `['array', 'null']`
      - type: `['array', 'null']`
    - `appearance`: `object (4 properties) | null`
      - type: `object (4 properties) | null`
    - `assistant`: `any`
      - type: `any`
    - `data_policy`: `object (10 properties) | null`
      - type: `object (10 properties) | null`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `identity_keys`: `['array', 'null']`
      - type: `['array', 'null']`
    - `idle_close_days`: `['integer', 'null']`
      - description: Days without a message before an open conversation closes (1 to 365).
      - type: `['integer', 'null']`
    - `name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `offline_policy`: `object (3 properties) | null`
      - type: `object (3 properties) | null`
    - `reply_email_enabled`: `['boolean', 'null']`
      - description: Mail agent replies to contacts with a verified reply address (S3.5a).
      - type: `['boolean', 'null']`
    - `trusted_issuers`: `['array', 'null']`
      - description: Replaces explicit OIDC trust, including `[]` to disable it. Omitted: unchanged.
      - type: `['array', 'null']`
- responses:
  - `200`: Channel updated; `warnings` names saved settings that will not work as configured, such as an EU region without an EU-declared AI key
    - `application/json`:
      - type: `object (21 properties)`
      - `agent_write_tools` *required*: `boolean`
        - description: N-D6: the assistant may propose the write tools of the channel's
        - type: `boolean`
      - `allowed_origins` *required*: `array<string>`
        - type: `array<string>`
      - `appearance` *required*: `object (4 properties)`
        - type: `object (4 properties)`
      - `assistant` *required*: `any`
        - type: `any`
      - `assistant_version` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `data_policy` *required*: `object (10 properties)`
        - type: `object (10 properties)`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `environment_id` *required*: `integer`
        - type: `integer`
      - `generated_identity_secrets`: `['array', 'null']`
        - type: `['array', 'null']`
      - `id` *required*: `integer`
        - type: `integer`
      - `identity_keys` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `idle_close_days` *required*: `integer`
        - description: Days without a message after which an open conversation is closed
        - type: `integer`
      - `name` *required*: `string`
        - type: `string`
      - `offline_policy` *required*: `object (3 properties)`
        - description: The channel's offline policy (spec §4 queue policy). The team is
        - type: `object (3 properties)`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `public_key` *required*: `string`
        - type: `string`
      - `reply_email_enabled` *required*: `boolean`
        - description: S3.5a (N-D5): an agent's reply is also mailed to a contact who has a
        - type: `boolean`
      - `trusted_issuers`: `['array', 'null']`
        - description: Explicit OIDC trust. `null` uses the environment's managed Identity;
        - type: `['array', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `warnings`: `array<object (5 properties)>`
        - description: Settings that are saved but will not work as configured, worked out
        - type: `array<object (5 properties)>`
  - `400`: Invalid channel settings
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}`

- operationId: `delete_channel`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Channel deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The channel has conversations; disable it instead
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/agents`

- operationId: `list_channel_agents`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Channel team
    - `application/json`:
      - type: `array<object (5 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/agents`

- operationId: `add_channel_agent`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `app_tenants`: `array<string>`
      - description: Omitted or empty: every app tenant of the channel.
      - type: `array<string>`
    - `role`: `string`
      - type: `string`
    - `user_id` *required*: `integer`
      - type: `integer`
- responses:
  - `201`: Team member bound to the channel
    - `application/json`:
      - type: `object (5 properties)`
      - `app_tenants` *required*: `array<string>`
        - type: `array<string>`
      - `can_handle` *required*: `boolean`
        - type: `boolean`
      - `display_name` *required*: `string`
        - type: `string`
      - `role` *required*: `string`
        - type: `string`
      - `user_id` *required*: `integer`
        - type: `integer`
  - `400`: The user is not a member of the organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: max_support_agents reached
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/agents/{user_id}`

- operationId: `remove_channel_agent`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `user_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Team member removed
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/knowledge`

- operationId: `list_knowledge_documents`
- tags: `Support Knowledge`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The channel's knowledge documents (bodies omitted)
    - `application/json`:
      - type: `array<object (8 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/knowledge`

- operationId: `create_knowledge_document`
- tags: `Support Knowledge`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `content` *required*: `string`
      - type: `string`
    - `source_kind`: `string`
      - description: The format of a document body.
      - type: `string`
    - `title` *required*: `string`
      - type: `string`
- responses:
  - `201`: Document chunked and indexed; `embedded` is false when only lexical search covers it
    - `application/json`:
      - type: `object (8 properties)`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `chunks` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `embedded` *required*: `boolean`
        - description: Whether every chunk carries an embedding (semantic search covers it).
        - type: `boolean`
      - `id` *required*: `integer`
        - type: `integer`
      - `source_kind` *required*: `string`
        - description: The format of a document body.
        - type: `string`
      - `status` *required*: `string`
        - type: `string`
      - `title` *required*: `string`
        - type: `string`
  - `400`: Empty or over-long title or content
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The channel holds 200 documents
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/knowledge/search`

- operationId: `search_knowledge`
- tags: `Support Knowledge`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `limit`: `['integer', 'null']`
      - description: At most 10; default 5.
      - type: `['integer', 'null']`
    - `query` *required*: `string`
      - type: `string`
- responses:
  - `200`: Cited chunks; `mode = lexical` with `degraded = true` when semantic search is unavailable
    - `application/json`:
      - type: `object (3 properties)`
      - `degraded` *required*: `boolean`
        - description: `true` when semantic search was unavailable (no embedder of the
        - type: `boolean`
      - `mode` *required*: `string`
        - description: How a search ranked its results.
        - type: `string`
      - `results` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
  - `400`: Empty or over-long query
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/knowledge/{document_id}`

- operationId: `delete_knowledge_document`
- tags: `Support Knowledge`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `document_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Document and its chunks deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown document, channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/notification-recipients`

- operationId: `get_notification_recipients`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Configured and effective human handoff recipients
    - `application/json`:
      - type: `object (3 properties)`
      - `configured` *required*: `array<object (3 properties)>`
        - description: The members configured for this channel (empty: the default applies).
        - type: `array<object (3 properties)>`
      - `effective` *required*: `array<object (3 properties)>`
        - description: Who receives the next human handoff mail of a conversation without an app
        - type: `array<object (3 properties)>`
      - `source` *required*: `string`
        - description: Where a channel's human handoff mail goes (spec §4 queue policy).
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/notification-recipients`

- operationId: `update_notification_recipients`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `user_ids` *required*: `array<integer>`
      - description: Numeric `users.id`s, at most 50.
      - type: `array<integer>`
- responses:
  - `200`: Recipients replaced; an empty list restores the default
    - `application/json`:
      - type: `object (3 properties)`
      - `configured` *required*: `array<object (3 properties)>`
        - description: The members configured for this channel (empty: the default applies).
        - type: `array<object (3 properties)>`
      - `effective` *required*: `array<object (3 properties)>`
        - description: Who receives the next human handoff mail of a conversation without an app
        - type: `array<object (3 properties)>`
      - `source` *required*: `string`
        - description: Where a channel's human handoff mail goes (spec §4 queue policy).
        - type: `string`
  - `400`: Too many, or a user who is not an eligible member of the organization
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/presence`

- operationId: `get_channel_presence`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: Who is online and whether the team is available
    - `application/json`:
      - type: `object (4 properties)`
      - `available` *required*: `boolean`
        - description: Whether a contact entering the queue now, in a conversation without an
        - type: `boolean`
      - `decided_by` *required*: `string`
        - description: What decided `available`: `agent_online`, `business_hours`, `outside_hours` or
        - type: `string`
      - `online` *required*: `array<object (4 properties)>`
        - description: Members online now, by name. Empty: nobody is online.
        - type: `array<object (4 properties)>`
      - `within_business_hours`: `['boolean', 'null']`
        - description: Inside the channel's business hours; `null` when it sets none.
        - type: `['boolean', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/channels/{id}/tools`

- operationId: `list_channel_tools`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: The channel's tool namespaces and each tool's resolution for a support turn
    - `application/json`:
      - type: `object (2 properties)`
      - `namespaces` *required*: `array<string>`
        - description: `assistant.tool_namespaces`.
        - type: `array<string>`
      - `tools` *required*: `array<object (15 properties)>`
        - description: Every tool of those namespaces in the organization, by namespace and
        - type: `array<object (15 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/contacts/{id}`

- operationId: `update_contact`
- tags: `Support Data Protection`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `ai_opt_out`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `display_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `traits`: `any`
      - type: `any`
- responses:
  - `200`: Contact rectified
    - `application/json`:
      - type: `any`
  - `400`: Invalid profile fields
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown contact or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/contacts/{id}`

- operationId: `erase_contact`
- tags: `Support Data Protection`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Erasure accepted; an erasure-journal entry is written before row deletion (joint contract SG-01)
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown contact or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The independent erasure journal is unavailable or Support is replaying it: no personal data was deleted. When the journal write failed, the contact's widget sessions, turns and human handoff mails are already revoked and the erasure completes once the journal is available
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/contacts/{id}/export`

- operationId: `export_contact`
- tags: `Support Data Protection`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `200`: GDPR export: the contact-visible messages plus the internal notes about the contact, the AI case summary (`metadata.event = case.summary`) included
    - `application/json`:
      - type: `object (4 properties)`
      - `contact` *required*: `object (10 properties)`
        - type: `object (10 properties)`
      - `conversations` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `other_channels`: `array<object (5 properties)>`
        - description: The same person's contacts in the project's other channels (the same
        - type: `array<object (5 properties)>`
      - `processing_purposes` *required*: `array<string>`
        - type: `array<string>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown contact or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/claim`

- operationId: `claim_conversation`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `expected_owner_version` *required*: `integer`
      - type: `integer`
- responses:
  - `200`: Conversation claimed; owner.changed is persisted
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Lost optimistic concurrency: https://conusai.com/probs/support-owner-changed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/drafts`

- operationId: `create_draft`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `201`: An internal AI draft for the owning agent; never shown to the contact
    - `application/json`:
      - type: `object (5 properties)`
      - `ai_generated` *required*: `boolean`
        - description: Always `true`: the console labels it as written by AI.
        - type: `boolean`
      - `citations` *required*: `any`
        - description: Knowledge-base sources the draft drew on.
        - type: `any`
      - `content` *required*: `string`
        - type: `string`
      - `draft_state` *required*: `string`
        - description: `pending` until the agent sends or discards it.
        - type: `string`
      - `seq` *required*: `integer`
        - type: `integer`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session; or the contact objected to automated handling
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The caller does not own the conversation, or it has no messages yet
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: No AI available, or the draft call failed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/drafts/{seq}/discard`

- operationId: `discard_draft`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `seq` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: The draft is discarded; nothing was sent
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown draft, conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The caller does not own the conversation, or the draft was settled
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/drafts/{seq}/send`

- operationId: `send_draft`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `seq` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `content` *required*: `string`
      - type: `string`
- responses:
  - `202`: The agent's reply (the draft, edited or not) sent to the contact; the draft is settled. A draft is sent once: a retry with the same text replays this reply
    - `application/json`:
      - type: `object (12 properties)`
      - `attachments`: `array<object (4 properties)>`
        - description: The files the message carries, in upload order.
        - type: `array<object (4 properties)>`
      - `author_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `author_kind` *required*: `string`
        - type: `string`
      - `content` *required*: `string`
        - type: `string`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - type: `string`
      - `metadata` *required*: `any`
        - type: `any`
      - `seq` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `visibility` *required*: `string`
        - type: `string`
  - `400`: Invalid content
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown draft, conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The caller does not own the conversation, or the draft was already sent with other text
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/events`

- operationId: `stream_conversation_events_agent`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `after` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: SSE stream of the conversation log (spec §8); internal visibility rows included for agents
    - `text/event-stream`:
      - type: `any`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/files`

- operationId: `upload_agent_file`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `multipart/form-data`:
    - type: `object (1 properties)`
    - `file` *required*: `string`
      - description: The file. Its kind is read from its bytes and must be one the
      - type: `string`
- responses:
  - `201`: Stored, sealed with the contact's key; pending until a reply sends it by file_id
    - `application/json`:
      - type: `object (4 properties)`
      - `content_type` *required*: `string`
        - description: The type read from the file's bytes, not the name.
        - type: `string`
      - `file_id` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - description: The name it was uploaded with.
        - type: `string`
      - `size_bytes` *required*: `integer`
        - type: `integer`
  - `400`: Not multipart, no file field, or an empty file
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused), or the channel takes no attachments
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The conversation is closed, or too many unsent uploads
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Larger than the channel's max_file_size_mb
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `415`: A kind the channel does not accept
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: No Blob store for attachments, or too many uploads in progress on this server (Retry-After)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/files/{file_id}`

- operationId: `download_agent_file`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `file_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The file, as an attachment (nosniff, no-store); audited as SUPPORT_ATTACHMENT_DOWNLOADED
    - `application/octet-stream`:
      - type: `any`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not a sent file of this conversation or an own unsent upload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: No Blob store for attachments
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/files/{file_id}`

- operationId: `delete_agent_file`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
  - `file_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: The unsent upload and its object are deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not an unsent upload of this agent in this conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/notes`

- operationId: `add_note`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `content` *required*: `string`
      - type: `string`
    - `expected_owner_version`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `202`: Internal note accepted; always internal visibility
    - `application/json`:
      - type: `object (12 properties)`
      - `attachments`: `array<object (4 properties)>`
        - description: The files the message carries, in upload order.
        - type: `array<object (4 properties)>`
      - `author_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `author_kind` *required*: `string`
        - type: `string`
      - `content` *required*: `string`
        - type: `string`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - type: `string`
      - `metadata` *required*: `any`
        - type: `any`
      - `seq` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `visibility` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/release`

- operationId: `release_conversation`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `expected_owner_version` *required*: `integer`
      - type: `integer`
    - `to` *required*: `string`
      - type: `string`
- responses:
  - `200`: Conversation released to AI or queue; a running AI turn is superseded
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle via session (API keys refused)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Lost optimistic concurrency: https://conusai.com/probs/support-owner-changed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/conversations/{id}/tools`

- operationId: `list_conversation_tools`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The tools the conversation has bound, each at the version it pinned, with the tool's current version
    - `application/json`:
      - type: `object (2 properties)`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `tools` *required*: `array<object (5 properties)>`
        - description: In the order the conversation bound them.
        - type: `array<object (5 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/inbox/events`

- operationId: `stream_inbox_events`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `after` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: SSE stream of inbox changes: conversation.created, owner.changed, conversation.closed (schemas/support-events.schema.json shapes, conversation-scoped fields omitted where N/A)
    - `text/event-stream`:
      - type: `any`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:read
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/presence`

- operationId: `post_presence`
- tags: `Support Inbox`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `channel_id`: `['integer', 'null']`
      - description: Omitted: a heartbeat for every channel of the project the agent may
      - type: `['integer', 'null']`
    - `status` *required*: `string`
      - type: `string`
- responses:
  - `204`: Heartbeat accepted; online for 45 s
  - `400`: status must be online or away
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:handle
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/usage`

- operationId: `get_tenant_usage`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `metric` (path) *required*: `string`
  - `from` (path) *required*: `string`
  - `to` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The project's Support usage of one meter by app tenant; tenant quantities sum to the total
    - `application/json`:
      - type: `object (4 properties)`
      - `metric` *required*: `string`
        - type: `string`
      - `reconciled` *required*: `boolean`
        - description: Whether the tenant quantities sum to `total`.
        - type: `boolean`
      - `tenants` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
      - `total` *required*: `string`
        - description: The project's total of the meter for the period.
        - type: `string`
  - `400`: Unknown meter or invalid period
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin via session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks`

- operationId: `list_support_webhooks`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Webhook endpoints of the project; secrets are never listed
    - `application/json`:
      - type: `array<object (11 properties)>`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks`

- operationId: `create_support_webhook`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `channel_id`: `['integer', 'null']`
      - type: `['integer', 'null']`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `events` *required*: `array<string>`
      - type: `array<string>`
    - `include_content`: `boolean`
      - description: Opt in to message content in `message.created` (default `false`).
      - type: `boolean`
    - `url` *required*: `string`
      - description: An `https` URL; admitted by the organization's egress policy.
      - type: `string`
- responses:
  - `201`: Webhook endpoint created; the Standard Webhooks secret is shown once
    - `application/json`:
      - type: `object (11 properties)`
      - `channel_id`: `['integer', 'null']`
        - description: The channel (numeric id) whose events are sent; `null` for every
        - type: `['integer', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - description: Subscribed events: `conversation.created`,
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_content` *required*: `boolean`
        - description: `message.created` carries the message text only when set.
        - type: `boolean`
      - `previous_secret_expires_at`: `['string', 'null']`
        - description: While set, deliveries are signed with the previous secret too (a
        - type: `['string', 'null']`
      - `secret`: `['string', 'null']`
        - description: The Standard Webhooks secret (`whsec_...`): only in the create and
        - type: `['string', 'null']`
      - `secret_rotated_at`: `['string', 'null']`
        - description: When the secret was last rotated; `null` if never.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid url, events or channel, or a url the egress policy refuses
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PATCH /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}`

- operationId: `update_support_webhook`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `enabled`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `events`: `['array', 'null']`
      - type: `['array', 'null']`
    - `include_content`: `['boolean', 'null']`
      - type: `['boolean', 'null']`
    - `url`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Webhook endpoint updated
    - `application/json`:
      - type: `object (11 properties)`
      - `channel_id`: `['integer', 'null']`
        - description: The channel (numeric id) whose events are sent; `null` for every
        - type: `['integer', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - description: Subscribed events: `conversation.created`,
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_content` *required*: `boolean`
        - description: `message.created` carries the message text only when set.
        - type: `boolean`
      - `previous_secret_expires_at`: `['string', 'null']`
        - description: While set, deliveries are signed with the previous secret too (a
        - type: `['string', 'null']`
      - `secret`: `['string', 'null']`
        - description: The Standard Webhooks secret (`whsec_...`): only in the create and
        - type: `['string', 'null']`
      - `secret_rotated_at`: `['string', 'null']`
        - description: When the secret was last rotated; `null` if never.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: Invalid url or events
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}`

- operationId: `delete_support_webhook`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `204`: Webhook endpoint and its delivery log deleted
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}/deliveries`

- operationId: `list_webhook_deliveries`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `before` (query): `integer`
  - `limit` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: One page of the endpoint's deliveries, newest first (the delivery log); pass the last id as `before` for the next page
    - `application/json`:
      - type: `array<object (14 properties)>`
  - `400`: Invalid before or limit
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}/deliveries/{delivery_id}/redeliver`

- operationId: `redeliver_webhook_delivery`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
  - `delivery_id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: Queued through the outbox for one more attempt with the same `webhook-id`, so the receiver can deduplicate
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `delivered_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `event_type` *required*: `string`
        - description: One of the subscribable events, or `support.test` for a test event
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_attempt_at`: `['string', 'null']`
        - description: When the last attempt was made.
        - type: `['string', 'null']`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_latency_ms`: `['integer', 'null']`
        - description: The last attempt's time until the receiver's response headers, in
        - type: `['integer', 'null']`
      - `last_status`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `next_attempt_at` *required*: `string`
        - type: `string`
      - `redelivered_at`: `['string', 'null']`
        - description: The last redelivery request.
        - type: `['string', 'null']`
      - `redeliveries`: `integer`
        - description: How many times an owner or admin asked to redeliver it.
        - type: `integer`
      - `state` *required*: `string`
        - description: `pending`, `sending`, `delivered`, `failed` or `skipped`.
        - type: `string`
      - `webhook_id` *required*: `string`
        - description: The `webhook-id` header value, the same on every retry.
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown delivery, endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The delivery is not failed or skipped, is about an erased contact (the `contact.erased` announcement itself, ids only, may be redelivered), is a test event, or the endpoint is disabled
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}/rotate-secret`

- operationId: `rotate_webhook_secret`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `overlap_seconds`: `['integer', 'null']`
      - description: How long the previous secret keeps signing next to the new one, in
      - type: `['integer', 'null']`
- responses:
  - `200`: Secret rotated; the new `whsec_` secret is shown once. The previous secret keeps signing deliveries next to it until `previous_secret_expires_at`
    - `application/json`:
      - type: `object (11 properties)`
      - `channel_id`: `['integer', 'null']`
        - description: The channel (numeric id) whose events are sent; `null` for every
        - type: `['integer', 'null']`
      - `created_at` *required*: `string`
        - type: `string`
      - `enabled` *required*: `boolean`
        - type: `boolean`
      - `events` *required*: `array<string>`
        - description: Subscribed events: `conversation.created`,
        - type: `array<string>`
      - `id` *required*: `integer`
        - type: `integer`
      - `include_content` *required*: `boolean`
        - description: `message.created` carries the message text only when set.
        - type: `boolean`
      - `previous_secret_expires_at`: `['string', 'null']`
        - description: While set, deliveries are signed with the previous secret too (a
        - type: `['string', 'null']`
      - `secret`: `['string', 'null']`
        - description: The Standard Webhooks secret (`whsec_...`): only in the create and
        - type: `['string', 'null']`
      - `secret_rotated_at`: `['string', 'null']`
        - description: When the secret was last rotated; `null` if never.
        - type: `['string', 'null']`
      - `updated_at` *required*: `string`
        - type: `string`
      - `url` *required*: `string`
        - type: `string`
  - `400`: overlap_seconds is outside 0 to 604800
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/orgs/{org}/workspaces/{ws}/projects/{project}/support/webhooks/{id}/test`

- operationId: `send_webhook_test_event`
- tags: `Support Channels`
- parameters:
  - `org` (path) *required*: `string`
  - `ws` (path) *required*: `string`
  - `project` (path) *required*: `string`
  - `id` (path) *required*: `integer`
- requestBody: _(none)_
- responses:
  - `202`: One `support.test` event queued through the outbox to this endpoint only, whatever it subscribed to: signed like every delivery, `data` is `{"endpoint": "<id>"}` and nothing else, one attempt. Its status code and latency appear in the delivery log
    - `application/json`:
      - type: `object (14 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `delivered_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `event_type` *required*: `string`
        - description: One of the subscribable events, or `support.test` for a test event
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `last_attempt_at`: `['string', 'null']`
        - description: When the last attempt was made.
        - type: `['string', 'null']`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `last_latency_ms`: `['integer', 'null']`
        - description: The last attempt's time until the receiver's response headers, in
        - type: `['integer', 'null']`
      - `last_status`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `next_attempt_at` *required*: `string`
        - type: `string`
      - `redelivered_at`: `['string', 'null']`
        - description: The last redelivery request.
        - type: `['string', 'null']`
      - `redeliveries`: `integer`
        - description: How many times an owner or admin asked to redeliver it.
        - type: `integer`
      - `state` *required*: `string`
        - description: `pending`, `sending`, `delivered`, `failed` or `skipped`.
        - type: `string`
      - `webhook_id` *required*: `string`
        - description: The `webhook-id` header value, the same on every retry.
        - type: `string`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Requires support:admin
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown endpoint or scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The endpoint is disabled, or a test of it is still waiting or being sent
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/privacy/app-requests`

- operationId: `create_app_partition_privacy_request`
- tags: `Privacy`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `kind` *required*: `string`
      - description: What a request does.
      - type: `string`
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `202`: Accepted
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `400`: Only kind is accepted
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Current self-service authority required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Binding prerequisite unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: App privacy prerequisites unavailable
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/privacy/app-requests/{request_id}`

- operationId: `get_app_partition_privacy_request`
- tags: `Privacy`
- parameters:
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `403`: Current self-service authority required
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No request for this member/binding
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/privacy/app-requests/{request_id}/export`

- operationId: `download_app_partition_privacy_export`
- tags: `Privacy`
- parameters:
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: OK
    - `application/json`:
      - type: `object (7 properties)`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `format` *required*: `string`
        - description: Always `conusai.privacy.export/v1`.
        - type: `string`
      - `generated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `request_id` *required*: `string`
        - type: `string`
      - `stores` *required*: `object`
        - description: Each store's export document, by store name.
        - type: `object`
      - `subject` *required*: `object (1 properties)`
        - description: The person an export is about: only the kind of key, never its value.
        - type: `object (1 properties)`
  - `404`: No request for this member/binding
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Export incomplete or expired
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/privacy/requests`

- operationId: `create_app_privacy_request`
- summary: Ask for erasure or export of one of the app's users (or visitors).
- tags: `Privacy`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `kind` *required*: `string`
      - description: What a request does.
      - type: `string`
    - `subject` *required*: `object (2 properties)`
      - description: Exactly one key names the person.
      - type: `object (2 properties)`
- responses:
  - `200`: An open request for the same kind and person
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `202`: Request created
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `400`: Not exactly one subject key, or an invalid one
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Not a deployment token holding privacy:subjects
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/privacy/requests/{request_id}`

- operationId: `get_app_privacy_request`
- summary: One request the app made.
- tags: `Privacy`
- parameters:
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The request
    - `application/json`:
      - type: `object (13 properties)`
      - `attempts` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `export_expires_at`: `['string', 'null']`
        - description: Exports only: when the export document is deleted.
        - type: `['string', 'null']`
      - `finished_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `id` *required*: `string`
        - type: `string`
      - `kind` *required*: `string`
        - description: What a request does.
        - type: `string`
      - `last_error`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `requested_via` *required*: `string`
        - description: Who asked.
        - type: `string`
      - `started_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `status` *required*: `string`
        - description: Where a job is.
        - type: `string`
      - `stores` *required*: `object`
        - description: Per store (`session_replay`, `errors`, `proxy_logs`, `traces`,
        - type: `object`
      - `subject_kind` *required*: `string`
        - description: The subject keys.
        - type: `string`
  - `404`: No such request made by this project's tokens
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/privacy/requests/{request_id}/export`

- operationId: `download_app_privacy_export`
- summary: The export document of a completed export the app requested.
- tags: `Privacy`
- parameters:
  - `request_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The export document
    - `application/json`:
      - type: `object (7 properties)`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `format` *required*: `string`
        - description: Always `conusai.privacy.export/v1`.
        - type: `string`
      - `generated_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `project_id` *required*: `integer`
        - type: `integer`
      - `request_id` *required*: `string`
        - type: `string`
      - `stores` *required*: `object`
        - description: Each store's export document, by store name.
        - type: `object`
      - `subject` *required*: `object (1 properties)`
        - description: The person an export is about: only the kind of key, never its value.
        - type: `object (1 properties)`
  - `404`: No such request made by this project's tokens
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Not ready, failed, expired, or an erasure
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/relay/enroll`

- operationId: `relay_enroll`
- summary: `POST /v1/relay/enroll`
- tags: `Relay`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `answer_to`: `['string', 'null']`
      - description: Set when ANSWERING an existing mailbox instead of opening one.
      - type: `['string', 'null']`
    - `endpoints`: `array<string>`
      - description: Candidate `host:port` endpoints (may be empty for NAT-ed nodes).
      - type: `array<string>`
    - `node_pubkey` *required*: `string`
      - description: This node's WG public key (base64 x25519, 44 chars).
      - type: `string`
    - `token` *required*: `string`
      - description: Join token authorizing this enrollment (validated, never stored).
      - type: `string`
- responses:
  - `200`: Answer recorded (when answer_to is set)
  - `201`: Mailbox opened
    - `application/json`:
      - type: `object (2 properties)`
      - `expires_in_secs` *required*: `integer`
        - description: Seconds until the mailbox expires (410 thereafter).
        - type: `integer`
      - `id` *required*: `string`
        - description: Mailbox id to poll via `GET /v1/relay/exchange/{id}`.
        - type: `string`
  - `400`: Malformed pubkey/endpoints
  - `403`: Invalid join token
  - `410`: Token already used at the relay, expired, or mailbox already answered
  - `429`: Rate limited
  - `500`: Internal server error

### `GET /v1/relay/exchange/{id}`

- operationId: `relay_exchange`
- summary: `GET /v1/relay/exchange/{id}` — long-poll ≤30 s for the counterpart.
- tags: `Relay`
- parameters:
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Counterpart pubkey+endpoint
    - `application/json`:
      - type: `object (2 properties)`
      - `answerer` *required*: `object (2 properties)`
        - description: One side of a relay mailbox: a WG public key plus candidate endpoints.
        - type: `object (2 properties)`
      - `offerer` *required*: `object (2 properties)`
        - description: One side of a relay mailbox: a WG public key plus candidate endpoints.
        - type: `object (2 properties)`
  - `204`: No counterpart within the long-poll window
  - `403`: Invalid join token
  - `404`: Unknown mailbox id
  - `410`: Mailbox expired or already consumed

### `GET /v1/sandboxes/rootfs`

- operationId: `rootfs_report`
- summary: Inspect rootfs storage: the Firecracker digest-keyed cache (with which
sandboxes reference each entry) and per-VM disks. Empty on Docker-only
hosts. Admin/read scope — this exposes host storage layout.
- tags: `Sandboxes`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Rootfs storage report

### `POST /v1/sandboxes/rootfs/gc`

- operationId: `rootfs_gc`
- summary: Reclaim rootfs cache entries not backing any live sandbox. Idempotent;
safe to call any time (live VMs hold their own per-VM disks).
- tags: `Sandboxes`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Reclaimed cache entries

### `GET /v1/service-types`

- operationId: `list_service_types`
- summary: GET /v1/service-types — every listed type, catalog order, no schemas.
- tags: `Service types`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of service types
    - `application/json`:
      - type: `array<any>`
  - `401`: Unauthorized

### `GET /v1/service-types/{service_type}`

- operationId: `get_service_type`
- summary: GET /v1/service-types/{service_type}
- tags: `Service types`
- parameters:
  - `service_type` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: Service type details
    - `application/json`:
      - type: `any`
  - `401`: Unauthorized
  - `404`: Service type not found
  - `500`: Internal server error

### `GET /v1/session/active-organization`

- operationId: `get_active_organization`
- summary: Read this session's organization scope.
- description: Re-verifies entitlement rather than echoing the stored id back. A
membership revoked since the switch must read as `null` here for the same
reason it must `404` at `ActiveOrg`: this response drives what the console
shows as the current tenant, and an id the user can no longer act in would
have the UI present an organization every subsequent request rejects.
- tags: `Organizations`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The session's current organization scope
    - `application/json`:
      - type: `object (3 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: `null` when the session has no organization scope — a user who belongs
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /v1/session/active-organization`

- operationId: `set_active_organization`
- summary: Switch this session to a different organization.
- description: Order of operations is the security property, so it is spelled out:
resolve the credential, look up existence and membership *both*
unconditionally, decide, and only then write. Nothing is written before the
decision, and the decision reads only server-side state.
- tags: `Organizations`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `organization_id` *required*: `integer`
      - description: The organization to switch this session to. Validated against the
      - type: `integer`
- responses:
  - `200`: Session switched
    - `application/json`:
      - type: `object (3 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: `null` when the session has no organization scope — a user who belongs
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Credential is not a browser session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No such organization, or the caller cannot reach it
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/session/active-workspace`

- operationId: `get_session_active_workspace`
- summary: Read this session's workspace scope.
- description: Re-validates access rather than echoing the stored id back, for the same
reason the org endpoint does: this response drives what the console shows
as the current workspace, and an id the user can no longer act in would
have the UI present a workspace that every subsequent request rejects.
Running the real `WorkspaceScope` extractor is what guarantees the two
agree — it is the same code path, not a second implementation of it.
- tags: `Workspaces`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The session's current workspace scope
    - `application/json`:
      - type: `object (4 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: The organization the workspace above belongs to, echoed so a client can
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
      - `workspace_id`: `string | null`
        - type: `string | null`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: The session has no organization scope
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `PUT /v1/session/active-workspace`

- operationId: `set_session_active_workspace`
- summary: Switch this session to a different workspace.
- description: Order of operations is the security property, so it is spelled out:
resolve the credential and its organization, validate the requested
workspace against the caller's real access with the same function every
scoped route uses, and only then write. Nothing is written before the
decision, and the decision reads only server-side state.
- tags: `Workspaces`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `workspace_id` *required*: `string`
      - description: Identifies a workspace, which belongs to exactly one organization.
      - type: `string`
- responses:
  - `200`: Session switched
    - `application/json`:
      - type: `object (4 properties)`
      - `name`: `['string', 'null']`
        - type: `['string', 'null']`
      - `organization_id`: `['integer', 'null']`
        - description: The organization the workspace above belongs to, echoed so a client can
        - type: `['integer', 'null']`
      - `slug`: `['string', 'null']`
        - type: `['string', 'null']`
      - `workspace_id`: `string | null`
        - type: `string | null`
  - `400`: Credential is not a browser session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Unauthorized
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: No such workspace, or the caller cannot reach it
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `500`: Internal Server Error
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/bound-thread-replies`

- operationId: `receive`
- tags: `Support Contact`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (5 properties)`
    - `content` *required*: `string`
      - type: `string`
    - `message_id` *required*: `string`
      - type: `string`
    - `provider` *required*: `string`
      - type: `string`
    - `thread_id` *required*: `string`
      - type: `string`
    - `token` *required*: `string`
      - type: `string`
- responses:
  - `202`: Reply appended or the provider message was already appended
  - `400`: Malformed reply
  - `401`: Invalid bound-thread token
  - `403`: Agent is not a member of this channel
  - `409`: Conversation is closed

### `GET /v1/support/channels/{public_key}/agent-card.json`

- operationId: `get`
- tags: `Support Contact`
- parameters:
  - `public_key` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The channel's explicitly enabled A2A Agent Card
  - `404`: Unknown channel or A2A metadata not enabled

### `POST /v1/support/channels/{public_key}/anonymous-widget-sessions`

- operationId: `post_anonymous_widget_session`
- tags: `Support Contact`
- parameters:
  - `public_key` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `501`: Deferred: anonymous mode is disabled; a public hosted-page URL alone grants no widget session (spec §5)

### `GET /v1/support/channels/{public_key}/config`

- operationId: `get_public_channel_config`
- tags: `Support Contact`
- parameters:
  - `public_key` (path) *required*: `string`
  - `locale` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Public appearance and greeting only; no identity, team or data-policy fields
    - `application/json`:
      - type: `object (7 properties)`
      - `appearance` *required*: `object (4 properties)`
        - description: The appearance a widget reads (`GET …/channels/{public_key}/config`):
        - type: `object (4 properties)`
      - `attachments` *required*: `object (4 properties)`
        - description: What a channel accepts as attachments (`data_policy.attachments`).
        - type: `object (4 properties)`
      - `greeting` *required*: `string`
        - description: The greeting for the requested `locale` (the visitor's locale, else
        - type: `string`
      - `greetings` *required*: `object`
        - description: A user-visible string per locale, as in guides: keys are BCP-47-ish tags (`en`, `lt`, `pt-BR`), values plain text. The widget shows the visitor's locale, else its language, else `en`, else the first locale. A request may still send a plain string, read as `{"en": "…"}`.
        - type: `object`
      - `name` *required*: `string`
        - type: `string`
      - `privacy_notice_url`: `['string', 'null']`
        - type: `['string', 'null']`
      - `public_key` *required*: `string`
        - type: `string`
  - `404`: Byte-identical 404 for unknown channel
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/channels/{public_key}/identify`

- operationId: `identify_with_token`
- tags: `Support Contact`
- parameters:
  - `public_key` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `grant_type`: `['string', 'null']`
      - type: `['string', 'null']`
    - `identity_token`: `string`
      - description: App-signed identity token (S1). Empty when RFC 8693 fields are used.
      - type: `string`
    - `subject_token`: `['string', 'null']`
      - type: `['string', 'null']`
    - `subject_token_type`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Identity token exchanged for a widget session
    - `application/json`:
      - type: `object (1 properties)`
      - `session` *required*: `object (3 properties)`
        - type: `object (3 properties)`
  - `401`: Forged signature, wrong aud, expired, replayed jti, key from another channel, or origin outside allowed_origins (no detail)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: More than 30 mints a minute from this IP or 600 an hour for the channel (Retry-After)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The app's JWKS could not be fetched
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/conversations`

- operationId: `list_own_conversations`
- tags: `Support Contact`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: The session contact's own conversations
    - `application/json`:
      - type: `array<object (9 properties)>`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations`

- operationId: `create_support_conversation`
- tags: `Support Contact`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object`
- responses:
  - `201`: Conversation created for the session's contact
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `402`: Plan limit reached, named in the problem detail
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown channel
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations/{id}/close`

- operationId: `close_conversation_contact`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (2 properties)`
    - `expected_owner_version` *required*: `integer`
      - type: `integer`
    - `reason` *required*: `string`
      - type: `string`
- responses:
  - `200`: Conversation closed by the contact; conversation.closed persisted
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for another contact's conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Lost optimistic concurrency: https://conusai.com/probs/support-owner-changed
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/conversations/{id}/events`

- operationId: `stream_conversation_events_contact`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
  - `after` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: SSE stream of the conversation log (spec §8); contact visibility only
    - `text/event-stream`:
      - type: `any`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins; another contact's conversation is a byte-identical 404
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for unknown conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations/{id}/files`

- operationId: `upload_contact_file`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
- requestBody:
  - `multipart/form-data`:
    - type: `object (1 properties)`
    - `file` *required*: `string`
      - description: The file. Its kind is read from its bytes and must be one the
      - type: `string`
- responses:
  - `201`: Stored, sealed with the contact's key; pending until a message sends it by file_id
    - `application/json`:
      - type: `object (4 properties)`
      - `content_type` *required*: `string`
        - description: The type read from the file's bytes, not the name.
        - type: `string`
      - `file_id` *required*: `string`
        - type: `string`
      - `name` *required*: `string`
        - description: The name it was uploaded with.
        - type: `string`
      - `size_bytes` *required*: `integer`
        - type: `integer`
  - `400`: Not multipart, no file field, or an empty file
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: The channel takes no attachments, or CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for another contact's conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: The conversation is closed and does not reopen, or too many unsent uploads
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `413`: Larger than the channel's max_file_size_mb
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `415`: A kind the channel does not accept
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Contact message rate exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: No Blob store for attachments, or too many uploads in progress on this server (Retry-After)
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/conversations/{id}/files/{file_id}`

- operationId: `download_contact_file`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
  - `file_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `200`: The file, as an attachment (nosniff, no-store)
    - `application/octet-stream`:
      - type: `any`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not a file of a contact-visible message or an own unsent upload
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: No Blob store for attachments
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/support/conversations/{id}/files/{file_id}`

- operationId: `delete_contact_file`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
  - `file_id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: The unsent upload and its object are deleted
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Not an unsent upload of this contact in this conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations/{id}/messages`

- operationId: `post_contact_message`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
  - `Idempotency-Key` (header) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `attachments`: `array<string>`
      - description: Files uploaded to this conversation by the sender and not yet sent,
      - type: `array<string>`
    - `content` *required*: `string`
      - description: The text; may be empty when the message carries attachments.
      - type: `string`
    - `expected_owner_version`: `['integer', 'null']`
      - type: `['integer', 'null']`
- responses:
  - `202`: Message persisted; returns its seq
    - `application/json`:
      - type: `object (12 properties)`
      - `attachments`: `array<object (4 properties)>`
        - description: The files the message carries, in upload order.
        - type: `array<object (4 properties)>`
      - `author_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `author_kind` *required*: `string`
        - type: `string`
      - `content` *required*: `string`
        - type: `string`
      - `conversation_id` *required*: `string`
        - type: `string`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `integer`
        - type: `integer`
      - `kind` *required*: `string`
        - type: `string`
      - `metadata` *required*: `any`
        - type: `any`
      - `seq` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `visibility` *required*: `string`
        - type: `string`
  - `400`: Missing or malformed Idempotency-Key
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for another contact's conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `409`: Idempotency-Key already names a different canonical request
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: Contact message rate exceeded
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations/{id}/reply-email`

- operationId: `collect_reply_email`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `reply_email` *required*: `string`
      - description: The address the authenticated contact explicitly asks replies to use.
      - type: `string`
- responses:
  - `204`: Reply-email consent stored for the session contact
  - `400`: Malformed reply_email
  - `401`: Invalid widget session
  - `404`: Byte-identical 404 for another contact's conversation
  - `409`: The channel does not use the collect_email offline policy

### `POST /v1/support/conversations/{id}/request-human`

- operationId: `request_human`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `202`: Human handoff requested; owner moves to queue, a running AI turn is superseded with turn.discarded
    - `application/json`:
      - type: `object (9 properties)`
      - `app_tenant`: `['string', 'null']`
        - type: `['string', 'null']`
      - `channel_id` *required*: `integer`
        - type: `integer`
      - `created_at` *required*: `string`
        - type: `string`
      - `id` *required*: `string`
        - type: `string`
      - `owner` *required*: `string`
        - type: `string`
      - `owner_agent_id`: `['integer', 'null']`
        - type: `['integer', 'null']`
      - `owner_version` *required*: `integer`
        - type: `integer`
      - `status` *required*: `string`
        - type: `string`
      - `updated_at` *required*: `string`
        - type: `string`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for another contact's conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/conversations/{id}/typing`

- operationId: `post_typing`
- tags: `Support Contact`
- parameters:
  - `id` (path) *required*: `string`
- requestBody: _(none)_
- responses:
  - `204`: Typing indicator accepted, rate-limited; ephemeral, never persisted
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for another contact's conversation
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/guide-offers`

- operationId: `list_guide_offers`
- tags: `Support Contact`
- parameters:
  - `locale` (query): `['string', 'null']`
  - `limit` (query): `['integer', 'null']`
- requestBody: _(none)_
- responses:
  - `200`: Guides the session's end user may be offered ("Show me"); empty when the Guides module is disabled or unavailable
    - `application/json`:
      - type: `object (1 properties)`
      - `offers` *required*: `array<object (3 properties)>`
        - type: `array<object (3 properties)>`
  - `401`: Invalid widget session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: CORS: origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/support/me`

- operationId: `erase_own_data`
- tags: `Support Data Protection`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `202`: Own erasure accepted; erasure-journal entry written before row deletion (joint contract SG-01). Only an account session the app's server minted (`account_session: true`) is accepted. It erases the person, every context, in the project's channels of the same environment under the same identity namespace, and in other environments' channels only where both channels opt in to `cross_environment_identity`
  - `401`: Invalid session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: A widget session (the browser's), or an origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: The independent erasure journal is unavailable or Support is replaying it: no personal data was deleted. When the journal write failed, the contact's widget sessions, turns and human handoff mails are already revoked and the erasure completes once the journal is available
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/me/export`

- operationId: `export_own_data`
- tags: `Support Data Protection`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Own GDPR export: exactly the contact-visible messages. Only an account session the app's server minted (`account_session: true`) is accepted. It exports the person in the project's channels of the same environment under the same identity namespace (`other_channels`), and in other environments' channels only where both channels opt in to `cross_environment_identity`. A session minted with an `app_tenant` exports that context only; without one, every context. The export is complete or refused: a channel's contact that cannot be exported fails the request, it is never left out
    - `application/json`:
      - type: `object (4 properties)`
      - `contact` *required*: `object (10 properties)`
        - type: `object (10 properties)`
      - `conversations` *required*: `array<object (4 properties)>`
        - type: `array<object (4 properties)>`
      - `other_channels`: `array<object (5 properties)>`
        - description: The same person's contacts in the project's other channels (the same
        - type: `array<object (5 properties)>`
      - `processing_purposes` *required*: `array<string>`
        - type: `array<string>`
  - `401`: Invalid session
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: A widget session (the browser's), or an origin outside allowed_origins
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `503`: A channel's share of the export could not be read: the export is refused, never returned without it
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `GET /v1/support/reply-email/unsubscribe`

- operationId: `reply_email_unsubscribe_page`
- tags: `Support Contact`
- parameters:
  - `token` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: A confirmation page; nothing changes until it is submitted (mail scanners fetch links)
    - `text/html`:
      - type: `any`

### `POST /v1/support/reply-email/unsubscribe`

- operationId: `reply_email_unsubscribe`
- tags: `Support Contact`
- parameters:
  - `token` (query): `string`
- requestBody: _(none)_
- responses:
  - `200`: Reply email is off for the contact the link was mailed to; its address is cleared
    - `text/html`:
      - type: `any`
  - `404`: Unknown token, or the conversation no longer exists
    - `text/html`:
      - type: `any`

### `POST /v1/support/widget-sessions`

- operationId: `mint_widget_session`
- tags: `Support Contact`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (10 properties)`
    - `account_session`: `boolean`
      - description: `true` mints an account session for the app's own account export and
      - type: `boolean`
    - `app_tenant`: `['string', 'null']`
      - type: `['string', 'null']`
    - `channel` *required*: `string`
      - type: `string`
    - `display_name`: `['string', 'null']`
      - type: `['string', 'null']`
    - `email`: `['string', 'null']`
      - type: `['string', 'null']`
    - `identity_namespace`: `['string', 'null']`
      - description: The identity namespace the app server maps its user into (joint
      - type: `['string', 'null']`
    - `identity_session`: `['string', 'null']`
      - description: The app's opaque reference to the identity session this mint runs
      - type: `['string', 'null']`
    - `reply_email`: `['string', 'null']`
      - description: S3.5a: an address the app has verified and its user agreed to receive
      - type: `['string', 'null']`
    - `subject` *required*: `string`
      - type: `string`
    - `traits`: `any`
      - type: `any`
- responses:
  - `201`: Widget session minted (sws_ token); with `account_session`, a five-minute account session for the app server's own export and erasure
    - `application/json`:
      - type: `object (3 properties)`
      - `conversation_defaults` *required*: `any`
        - type: `any`
      - `expires_at` *required*: `string`
        - type: `string`
      - `token` *required*: `string`
        - type: `string`
  - `400`: Invalid subject, app tenant or traits
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Invalid deployment token
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Token lacks support:widget-sessions or is not pinned to the channel's environment
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for an unknown channel or a channel of another project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `429`: More than 600 mints an hour for the channel (Retry-After); a server mint is not limited per IP
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `POST /v1/support/widget-sessions/revoke`

- operationId: `revoke_widget_sessions`
- tags: `Support Contact`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `channel` *required*: `string`
      - type: `string`
    - `identity_namespace`: `['string', 'null']`
      - type: `['string', 'null']`
    - `identity_session`: `['string', 'null']`
      - description: The identity session's opaque reference, as given to the mint.
      - type: `['string', 'null']`
    - `subject`: `['string', 'null']`
      - description: The subject whose widget sessions end (with `identity_namespace`, `app` when
      - type: `['string', 'null']`
- responses:
  - `200`: The matching widget sessions are revoked: the next request answers 401 and an open stream closes at its next keep-alive. With `subject`, the scope of the person's erasure: the channels of the token's project in its environment, and in other environments where both channels opt in to `cross_environment_identity`, for that identity namespace and subject; with `identity_session` alone, the named channel. Idempotent (revoked may be 0)
    - `application/json`:
      - type: `object (1 properties)`
      - `revoked` *required*: `integer`
        - description: How many live sessions ended; 0 is a success (idempotent).
        - type: `integer`
  - `400`: Neither subject nor identity_session, or an invalid one
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `401`: Invalid deployment token
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `403`: Token lacks support:widget-sessions or is not pinned to the channel's environment
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`
  - `404`: Byte-identical 404 for an unknown channel or a channel of another project
    - `application/json`:
      - type: `object (5 properties)`
      - `detail`: `['string', 'null']`
        - description: A human-readable explanation specific to this occurrence of the problem
        - type: `['string', 'null']`
      - `extensions` *required*: `object`
        - description: Additional properties of the problem
        - type: `object`
      - `instance`: `['string', 'null']`
        - description: A URI reference that identifies the specific occurrence of the problem
        - type: `['string', 'null']`
      - `title` *required*: `string`
        - description: A short, human-readable summary of the problem type
        - type: `string`
      - `type`: `['string', 'null']`
        - description: A URI reference that identifies the problem type
        - type: `['string', 'null']`

### `DELETE /v1/users/me`

- operationId: `delete_own_account`
- summary: Delete the caller's own console account. Sessions, personal API keys and
device logins end with this request; organization keys stay, being the
organization's. The account is removed after 30 days, and until then an
administrator can restore it.
- tags: `Users`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `202`: Deleted: every credential of the account has ended, and the purge removes it after 30 days
    - `application/json`:
      - type: `object (2 properties)`
      - `deleted_at` *required*: `string`
        - type: `string`
      - `purge_after` *required*: `string`
        - description: From this moment the purge removes the account; until then an
        - type: `string`
  - `401`: No browser session
  - `403`: A key or token, which can never do this
  - `409`: The sole owner of an organization with other members (`account-sole-owner`, listing `organizations`), or the last installation administrator (`account-last-admin`)
  - `428`: Recent step-up required (`step-up-required`)

### `POST /v1/users/me/email-change`

- operationId: `request_email_change`
- summary: Ask to change the account's email address.
- description: Steps up with the current password (and a second factor when MFA is
enrolled), then mails a 30-minute confirmation link to the new address
and a notice to the current one. The answer is 202 whether or not the new
address is free, so the endpoint is no account oracle.
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `mfa_code`: `['string', 'null']`
      - description: A TOTP or recovery code. Required when MFA is enrolled.
      - type: `['string', 'null']`
    - `new_email` *required*: `string`
      - type: `string`
    - `password`: `['string', 'null']`
      - description: The current password. Required when the account has one.
      - type: `['string', 'null']`
- responses:
  - `202`: Confirmation link sent to the new address
  - `400`: Invalid or unchanged address, or a missing second factor
  - `401`: Wrong password or second factor
  - `403`: Not a browser session
  - `409`: SSO-managed account, or no credential to confirm with

### `POST /v1/users/me/email-change/confirm`

- operationId: `confirm_email_change`
- summary: Confirm an email change with the token from the link.
- description: Moves the account to the new address (marked verified) and revokes every
session except the one confirming.
- tags: `Users`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (1 properties)`
    - `token` *required*: `string`
      - type: `string`
- responses:
  - `204`: Address changed; other sessions revoked
  - `400`: Invalid, expired, spent or foreign token
  - `403`: Not a browser session
  - `409`: The new address belongs to another account

### `GET /v1/users/me/export`

- operationId: `export_own_account`
- summary: Download everything held about the caller's own console account as one
JSON document. Needs a browser session with a recent step-up. A store that
cannot answer refuses the whole export: a person told "this is everything"
must not be handed part of it.
- tags: `Users`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Everything the installation holds about the caller's own account
    - `application/json`:
      - type: `object (5 properties)`
      - `account` *required*: `object (9 properties)`
        - description: The account part of `GET /v1/users/me/export`. An allow-list, built field
        - type: `object (9 properties)`
      - `generated_at` *required*: `string`
        - type: `string`
      - `memberships` *required*: `array<object (5 properties)>`
        - type: `array<object (5 properties)>`
      - `sessions` *required*: `array<object (2 properties)>`
        - type: `array<object (2 properties)>`
      - `stores` *required*: `object`
        - description: What each other store holds about the account, by store name.
        - type: `object`
  - `401`: No browser session
  - `403`: A key or token, which can never do this
  - `428`: Recent step-up required (`step-up-required`)
  - `503`: A store could not answer; no partial export is sent

### `POST /v1/vpn/enroll`

- operationId: `vpnEnroll`
- summary: Enrol a headless device with an enrolment token (Path B, spec §5c.1).
- description: Token-authenticated IN-HANDLER: the caller holds no session, and the
organization is carried by the token, not by the path — that is why this
route is not under the org-scope prefix, and it must not be moved there.
- tags: `VPN`
- parameters: _(none)_
- requestBody:
  - `application/json`:
    - type: `object (3 properties)`
    - `hostname`: `['string', 'null']`
      - description: The enrollee's hostname, used for the default name.
      - type: `['string', 'null']`
    - `name`: `['string', 'null']`
      - description: Optional device name; defaults to `{token-label}-{hostname}`.
      - type: `['string', 'null']`
    - `public_key` *required*: `string`
      - description: `WireGuard` public key, base64 (32 bytes).
      - type: `string`
- responses:
  - `200`: Device enrolled; the PSK is shown once
    - `application/json`:
      - type: `object (7 properties)`
      - `allowed_ips` *required*: `array<string>`
        - description: Split-tunnel destinations: the origin host's /32 plus the subnets the
        - type: `array<string>`
      - `anchor_endpoint` *required*: `string`
        - description: Public endpoint of the anchor's `wg-clients` interface, `host:port`.
        - type: `string`
      - `anchor_public_key` *required*: `string`
        - description: Public key of the anchor's `wg-clients` interface.
        - type: `string`
      - `expires_at`: `['string', 'null']`
        - type: `['string', 'null']`
      - `persistent_keepalive` *required*: `integer`
        - description: Required behind NAT (spec §5c: without it the tunnel goes quiet).
        - type: `integer`
      - `psk`: `['string', 'null']`
        - description: The per-peer PSK — present ONLY on the creating call, never re-emitted.
        - type: `['string', 'null']`
      - `tunnel_ip` *required*: `string`
        - description: The client's tunnel address, always a /32.
        - type: `string`
  - `401`: Invalid, expired, revoked or spent enrolment token
  - `409`: No anchor paired / anchor predates client VPN
  - `422`: Validation error

### `GET /version`

- operationId: `get_api_version`
- tags: `PlatformVersion`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Running console build and installed authorization plugin
    - `application/json`:
      - type: `object (5 properties)`
      - `authz_plugin` *required*: `object (6 properties)`
        - description: What is installed at the plugin path.
        - type: `object (6 properties)`
      - `build_time` *required*: `string`
        - description: When the console was built.
        - type: `string`
      - `bundle_version`: `['string', 'null']`
        - description: Vendor bundle version, when a bundle manifest is found.
        - type: `['string', 'null']`
      - `commit` *required*: `string`
        - description: Short commit hash the console was built from.
        - type: `string`
      - `version` *required*: `string`
        - description: Version tag of the running console, e.g. `v0.1.0-beta.86`.
        - type: `string`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `GET /visitors/{visitor_id}/session-replays`

- operationId: `get_visitor_sessions`
- summary: Get session replays for a visitor
- tags: `Analytics`
- parameters:
  - `visitor_id` (path) *required*: `integer`
  - `page` (query): `integer`
  - `per_page` (query): `integer`
- requestBody: _(none)_
- responses:
  - `200`: Session replays retrieved successfully
    - `application/json`:
      - type: `object (4 properties)`
      - `page` *required*: `integer`
        - type: `integer`
      - `per_page` *required*: `integer`
        - type: `integer`
      - `sessions` *required*: `array<object (30 properties)>`
        - type: `array<object (30 properties)>`
      - `total_count` *required*: `integer`
        - type: `integer`
  - `500`: Internal server error
    - `application/json`:
      - type: `object (2 properties)`
      - `details`: `['string', 'null']`
        - type: `['string', 'null']`
      - `error` *required*: `string`
        - type: `string`

### `GET /webhook-event-types`

- operationId: `list_event_types`
- summary: List available event types
- tags: `Webhooks`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of available event types
    - `application/json`:
      - type: `array<object (3 properties)>`

### `POST /weekly-digest/trigger`

- operationId: `trigger_weekly_digest`
- summary: Trigger weekly digest generation manually
- tags: `Notification Preferences`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Weekly digest triggered successfully
    - `application/json`:
      - type: `object (2 properties)`
      - `message` *required*: `string`
        - type: `string`
      - `success` *required*: `boolean`
        - type: `boolean`
  - `500`: Failed to generate digest

### `GET /x/plugins`

- operationId: `list_external_plugins`
- summary: List all running external plugins and their manifests.
- tags: `External Plugins`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: List of all running external plugins
    - `application/json`:
      - type: `array<object (9 properties)>`

### `POST /x/plugins/reload`

- operationId: `reload_plugins`
- summary: Reload all external plugins.
- description: Stops all running plugin processes, re-scans the plugins directory,
starts any discovered binaries, and hot-swaps the proxy router so new
and removed plugins take effect immediately without a server restart.

Requires `SystemAdmin` permission.
- tags: `External Plugins`
- parameters: _(none)_
- requestBody: _(none)_
- responses:
  - `200`: Plugins reloaded successfully
    - `application/json`:
      - type: `object (3 properties)`
      - `loaded` *required*: `integer`
        - description: Number of plugins successfully loaded after reload
        - type: `integer`
      - `message` *required*: `string`
        - description: Human-readable status message
        - type: `string`
      - `plugins` *required*: `array<string>`
        - description: Names of loaded plugins
        - type: `array<string>`
  - `401`: Unauthorized
  - `403`: Insufficient permissions

### `POST /{project_id}/envelope/`

- operationId: `ingest_sentry_envelope`
- summary: Ingest a Sentry envelope.
- description: Authenticated by the project's DSN public key — `sentry_key` query
parameter, `X-Sentry-Auth: Sentry sentry_key=…`, or `Authorization: DSN …`
— not by a platform bearer token. No `Content-Type` is required (browser
SDKs omit it to avoid a CORS preflight). Items are framed by their
`length`; an envelope without an `event` item (sessions, client reports)
is accepted. Items that are unsupported, malformed or over their limit are
discarded and counted; they never fail the envelope.
- tags: `sentry-ingestor`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `sentry_key` (query): `string`
- requestBody:
  - `application/x-sentry-envelope`:
    - type: `string`
- responses:
  - `200`: Envelope accepted
    - `application/json`:
      - type: `object (1 properties)`
      - `id`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Envelope header is not JSON, or the body cannot be decoded
  - `401`: Missing or invalid DSN key
  - `413`: Envelope over 20 MiB (compressed or decoded)
  - `415`: Unsupported Content-Encoding
  - `500`: An error event could not be stored

### `POST /{project_id}/store/`

- operationId: `ingest_sentry_event`
- summary: Ingest a single Sentry event (JSON body, legacy `/store/` protocol).
- description: Authenticated by the project's DSN public key — `sentry_key` query
parameter, `X-Sentry-Auth: Sentry sentry_key=…`, or `Authorization: DSN …`
— not by a platform bearer token. The body may be gzip, deflate or zstd
encoded. The event goes through the same pipeline as an envelope's
`event` item.
- tags: `sentry-ingestor`
- parameters:
  - `project_id` (path) *required*: `integer`
  - `sentry_key` (query): `string`
- requestBody:
  - `application/json`:
    - type: `object (4 properties)`
    - `event_id`: `['string', 'null']`
      - type: `['string', 'null']`
    - `message`: `['string', 'null']`
      - type: `['string', 'null']`
    - `platform`: `['string', 'null']`
      - type: `['string', 'null']`
    - `timestamp`: `['string', 'null']`
      - type: `['string', 'null']`
- responses:
  - `200`: Event accepted
    - `application/json`:
      - type: `object (1 properties)`
      - `id`: `['string', 'null']`
        - type: `['string', 'null']`
  - `400`: Body is not a Sentry event, or cannot be decoded
  - `401`: Missing or invalid DSN key
  - `413`: Body over 20 MiB, or event over 1 MiB after decoding
  - `415`: Unsupported Content-Encoding
  - `500`: The event could not be stored
