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

# HTTP API reference

Every route the Sediment server exposes, generated from the committed
`openapi.yaml` by `scripts/gen_api_docs.py`. Do not edit this file — change
the route, then run `uv run python scripts/dump_openapi.py` followed by
`uv run python scripts/gen_api_docs.py` (CI fails on a stale spec or page).

A deployment can also serve the spec itself — `/docs`, `/redoc`,
`/openapi.json` — but all three are closed unless docs are enabled.

New here? Start with the [quickstart](/quickstart); the client side of
these routes is the [CLI reference](/reference/cli).

## Conventions

Routers write facts only: no derived state is computed into storage on the
request path (ADR 0001). Tenancy binds to the deployment
(`SEDIMENT_ORG_ID`), never to the request — no route accepts an org.

* **Single-fact ingest** returns `{"fact_id": "<uuid>", "stored": <bool>}`.
  `stored: false` is a redelivery that collapsed on a UNIQUE index — success.
* **A declined payload** returns 200 `{"skipped": true, "reason": "<why>"}`,
  so a webhook sender does not retry what will never be stored.
* **Auth failures are 401**; a malformed body from an authenticated caller is
  400 or 422. A 500 is a bug, never a documented outcome.
* **Every body read is bounded** at 25 MiB, before authentication.

## Endpoints

Every route, in ingest → read order:

| Endpoint                                                                                                                | Auth                           | Purpose                                                                                       |
| ----------------------------------------------------------------------------------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------- |
| [`POST /ingest/gateway`](#post-/ingest/gateway)                                                                         | ingest or operator             | Inference-call facts from an LLM gateway.                                                     |
| [`POST /ingest/github/push`](#post-/ingest/github/push)                                                                 | HMAC signature                 | Push facts from a GitHub `push` webhook.                                                      |
| [`POST /ingest/github/repository`](#post-/ingest/github/repository)                                                     | HMAC signature                 | Immutable Repository rename receipts.                                                         |
| [`POST /ingest/github/ci`](#post-/ingest/github/ci)                                                                     | HMAC signature                 | CI outcome facts from a GitHub `workflow_run` webhook.                                        |
| [`POST /ingest/github/pull-request`](#post-/ingest/github/pull-request)                                                 | HMAC signature                 | Revision and merge-boundary facts from a GitHub `pull_request` webhook.                       |
| [`POST /ingest/ci`](#post-/ingest/ci)                                                                                   | ingest or operator             | CI outcome facts from any non-GitHub pipeline.                                                |
| [`POST /v1/logs`](#post-/v1/logs)                                                                                       | ingest or operator             | OTLP log records: developer decisions, edit observations, rejected edits, and retry linkages. |
| [`GET /query/evidence`](#get-/query/evidence)                                                                           | operator                       | Complete bounded metadata inventory for one Session.                                          |
| [`GET /query/evidence/manifest`](#get-/query/evidence/manifest)                                                         | operator                       | Message and part references for one captured Inference call.                                  |
| [`POST /query/evidence/read`](#post-/query/evidence/read)                                                               | operator                       | Read-only fetch of complete canonical parts by exact occurrence reference.                    |
| [`POST /query/context`](#post-/query/context)                                                                           | retrieval or operator          | Agent-requested evidence from the configured previous Session.                                |
| [`POST /query/context/discover`](#post-/query/context/discover)                                                         | retrieval or operator          | Discover relevant candidates within the authorized Session set.                               |
| [`POST /query/context/selected`](#post-/query/context/selected)                                                         | retrieval or operator          | Retrieve exact context from a selected authorized Session.                                    |
| [`GET /query/context/evidence`](#get-/query/context/evidence)                                                           | retrieval or operator          | Complete factual inventory within the authorized Session set.                                 |
| [`GET /query/context/evidence/manifest`](#get-/query/context/evidence/manifest)                                         | retrieval or operator          | Exact message-part references within the authorized Session set.                              |
| [`POST /query/context/evidence/read`](#post-/query/context/evidence/read)                                               | retrieval or operator          | Consumer-selected exact parts within the authorized Session set.                              |
| [`GET /query/ci/outcome`](#get-/query/ci/outcome)                                                                       | operator                       | One CI outcome identified by provider run and attempt.                                        |
| [`GET /query/ci/failures`](#get-/query/ci/failures)                                                                     | operator                       | Bounded failure-first CI outcome search.                                                      |
| [`GET /query/session/{session_id}`](#get-/query/session/session_id)                                                     | operator                       | Metadata evidence dossier for one Session.                                                    |
| [`GET /query/commit/{sha}`](#get-/query/commit/sha)                                                                     | operator                       | Observed Sessions and inferred call associations for one commit.                              |
| [`GET /v1/me`](#get-/v1/me)                                                                                             | ingest, operator, or retrieval | Auth probe: tenant, version, authority, and configured client.                                |
| [`GET /v1/facts`](#get-/v1/facts)                                                                                       | operator                       | Fact counts per table, total, and visible.                                                    |
| [`GET /v1/facts/session/{session_id}`](#get-/v1/facts/session/session_id)                                               | operator                       | Session-scoped fact counts for write verification.                                            |
| [`GET /v1/facts/session/{session_id}/inference-calls`](#get-/v1/facts/session/session_id/inference-calls)               | operator                       | Session-scoped Inference call fields for usage reconciliation.                                |
| [`GET /v1/facts/session/{session_id}/compatibility-evidence`](#get-/v1/facts/session/session_id/compatibility-evidence) | operator                       | Session-scoped decision, Edit observation, and inference join fields.                         |
| [`GET /v1/reports/model-outcomes`](#get-/v1/reports/model-outcomes)                                                     | operator                       | Bounded model-outcome evidence for operational decisions.                                     |
| [`GET /v1/reports/accepted-work-lifecycle`](#get-/v1/reports/accepted-work-lifecycle)                                   | operator                       | Bounded accepted-work lifecycle evidence for operational decisions.                           |
| [`GET /health`](#get-/health)                                                                                           | none                           | Liveness and version.                                                                         |

## POST /ingest/gateway

**Auth:** Bearer token from the named `SEDIMENT_INGEST_TOKENS` map or the legacy `$SEDIMENT_API_BEARER_TOKEN`. The operator token also permits explicit operator ingest. Missing or invalid credentials return 401; retrieval authority returns 403.

**Response:** Stores one inference-call fact: `{"fact_id": "<uuid>", "stored": <bool>}`. `stored: false` means a redelivery collapsed on a UNIQUE index (ADR 0003) — success, not an error. A call whose session cannot be resolved is declined with 200 `{"skipped": true, "reason": "no_session"}`.

Request body — `GatewayIngestRequest` (`application/json`):

| Field        | Type           | Required | Description                                        |
| ------------ | -------------- | -------- | -------------------------------------------------- |
| `provider`   | string         | yes      | one of `litellm`, `portkey`, `helicone`, `unknown` |
| `session_id` | string or null | no       | —                                                  |
| `user_id`    | string or null | no       | —                                                  |
| `payload`    | object         | yes      | —                                                  |
| `capture`    | object or null | no       | —                                                  |

Status codes:

| Status | Meaning                                                                                                                                      |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                          |
| `400`  | `provider` names a gateway with no adapter.                                                                                                  |
| `401`  | Missing or invalid credentials.                                                                                                              |
| `403`  | The credential lacks the authority required by this route.                                                                                   |
| `409`  | Primary and natural Inference call identities conflict; `detail.code` is `inference_call_identity_conflict`. No foreign Fact ID is returned. |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                             |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.      |

## POST /ingest/github/push

**Auth:** GitHub webhook signature — `X-Hub-Signature-256`, HMAC-SHA256 over the raw body keyed with `SEDIMENT_GITHUB_WEBHOOK_SECRET`. The signature is verified **before** the event type is examined, so a misconfigured webhook cannot green-light itself with a setup ping.

**Response:** `{"fact_id": "<uuid>", "stored": <bool>}`. A non-`push` `X-GitHub-Event`, or a push carrying nothing storable, returns 200 `{"skipped": true, "reason": "<why>"}` so GitHub stops retrying. A stored push may schedule a background mirror refresh and re-derivation; that result is one log line, never stored (ADR 0001).

Parameters:

| Name             | In     | Type   | Required |
| ---------------- | ------ | ------ | -------- |
| `x-github-event` | header | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                    |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                        |
| `400`  | Signature valid, but the body is not a JSON object — a malformed request from an authenticated sender, so 400, not 401 (`deps.py::read_verified_webhook`). |
| `401`  | Missing or invalid credentials.                                                                                                                            |
| `409`  | Repository identity conflicts with a retained receipt; `detail.code` is `repository_identity_conflict`. No foreign Fact ID is returned.                    |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                                           |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                    |
| `503`  | PostgreSQL Fact store unavailable; the request does not acknowledge successful storage.                                                                    |

## POST /ingest/github/repository

Store an immutable rename receipt independently of mirror availability.

**Auth:** GitHub webhook signature — `X-Hub-Signature-256`, HMAC-SHA256 over the raw body keyed with `SEDIMENT_GITHUB_WEBHOOK_SECRET`. The signature is verified **before** the event type is examined, so a misconfigured webhook cannot green-light itself with a setup ping.

**Response:** `{"fact_id": "<uuid>", "stored": <bool>}` after storage, including when mirrors are disabled. A declined event returns 200 `{"skipped": true, "reason": "<why>"}`. Renames never move an identified mirror.

Parameters:

| Name                | In     | Type           | Required |
| ------------------- | ------ | -------------- | -------- |
| `x-github-event`    | header | string         | yes      |
| `x-github-delivery` | header | string or null | no       |

Status codes:

| Status | Meaning                                                                                                                                                    |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                        |
| `400`  | Signature valid, but the body is not a JSON object — a malformed request from an authenticated sender, so 400, not 401 (`deps.py::read_verified_webhook`). |
| `401`  | Missing or invalid credentials.                                                                                                                            |
| `409`  | Repository identity conflicts with a retained receipt; `detail.code` is `repository_identity_conflict`. No foreign Fact ID is returned.                    |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                                           |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                    |
| `503`  | PostgreSQL Fact store unavailable; the request does not acknowledge successful storage.                                                                    |

## POST /ingest/github/ci

**Auth:** GitHub webhook signature — `X-Hub-Signature-256`, HMAC-SHA256 over the raw body keyed with `SEDIMENT_GITHUB_WEBHOOK_SECRET`. The signature is verified **before** the event type is examined, so a misconfigured webhook cannot green-light itself with a setup ping.

**Response:** `{"fact_id": "<uuid>", "stored": <bool>}` for a completed `workflow_run`. Any other event, or a run still in flight, returns 200 `{"skipped": true, "reason": "<why>"}`.

Parameters:

| Name                | In     | Type           | Required |
| ------------------- | ------ | -------------- | -------- |
| `x-github-event`    | header | string         | yes      |
| `x-github-delivery` | header | string or null | no       |

Status codes:

| Status | Meaning                                                                                                                                                    |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                        |
| `400`  | Signature valid, but the body is not a JSON object — a malformed request from an authenticated sender, so 400, not 401 (`deps.py::read_verified_webhook`). |
| `401`  | Missing or invalid credentials.                                                                                                                            |
| `409`  | Repository identity conflicts with a retained receipt; `detail.code` is `repository_identity_conflict`. No foreign Fact ID is returned.                    |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                                           |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                    |
| `503`  | PostgreSQL Fact store unavailable; the request does not acknowledge successful storage.                                                                    |

## POST /ingest/github/pull-request

**Auth:** GitHub webhook signature — `X-Hub-Signature-256`, HMAC-SHA256 over the raw body keyed with `SEDIMENT_GITHUB_WEBHOOK_SECRET`. The signature is verified **before** the event type is examined, so a misconfigured webhook cannot green-light itself with a setup ping.

**Response:** `{"fact_id": "<uuid>", "stored": <bool>}` for an opened, synchronized, or merged pull request. Another event type, an unmerged closure, or a malformed boundary returns 200 `{"skipped": true, "reason": "<why>"}`.

Parameters:

| Name                | In     | Type           | Required |
| ------------------- | ------ | -------------- | -------- |
| `x-github-event`    | header | string         | yes      |
| `x-github-delivery` | header | string or null | no       |

Status codes:

| Status | Meaning                                                                                                                                                    |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                        |
| `400`  | Signature valid, but the body is not a JSON object — a malformed request from an authenticated sender, so 400, not 401 (`deps.py::read_verified_webhook`). |
| `401`  | Missing or invalid credentials.                                                                                                                            |
| `409`  | Repository identity conflicts with a retained receipt; `detail.code` is `repository_identity_conflict`. No foreign Fact ID is returned.                    |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                                           |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                    |
| `503`  | PostgreSQL Fact store unavailable; the request does not acknowledge successful storage.                                                                    |

## POST /ingest/ci

**Auth:** Bearer token from the named `SEDIMENT_INGEST_TOKENS` map or the legacy `$SEDIMENT_API_BEARER_TOKEN`. The operator token also permits explicit operator ingest. Missing or invalid credentials return 401; retrieval authority returns 403.

**Response:** `{"fact_id": "<uuid>", "stored": <bool>}`. The envelope forbids unknown fields: a caller naming an org or inventing a field is rejected at the door, not ignored.

Request body — `VendorCIRequest` (`application/json`):

| Field                 | Type            | Required | Description                                                                                                                                                                                               |
| --------------------- | --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`            | string          | yes      | The normalized CI system. The sender declares it from integration configuration; Sediment does not infer it from a URL; one of `github_actions`, `jenkins`, `gitlab_ci`, `circleci`, `buildkite`, `other` |
| `run_id`              | string          | yes      | The provider-issued pipeline-run id, unique within the deployment organization and provider namespace                                                                                                     |
| `run_attempt`         | integer or null | no       | —                                                                                                                                                                                                         |
| `repo`                | string          | yes      | —                                                                                                                                                                                                         |
| `repository_provider` | string or null  | no       | —                                                                                                                                                                                                         |
| `repository_host`     | string or null  | no       | —                                                                                                                                                                                                         |
| `repository_id`       | string or null  | no       | —                                                                                                                                                                                                         |
| `commit_sha`          | string          | yes      | —                                                                                                                                                                                                         |
| `branch`              | string          | yes      | —                                                                                                                                                                                                         |
| `workflow_name`       | string          | no       | default `""`                                                                                                                                                                                              |
| `workflow_id`         | string or null  | no       | —                                                                                                                                                                                                         |
| `workflow_path`       | string or null  | no       | —                                                                                                                                                                                                         |
| `result`              | string          | yes      | one of `passed`, `failed`, `error`, `timed_out`, `cancelled`, `skipped`, `neutral`, `unknown`                                                                                                             |
| `run_url`             | string or null  | no       | —                                                                                                                                                                                                         |
| `provider_result`     | string or null  | no       | —                                                                                                                                                                                                         |
| `error_type`          | string or null  | no       | —                                                                                                                                                                                                         |
| `reason`              | string or null  | no       | —                                                                                                                                                                                                         |
| `source_event_type`   | string or null  | no       | —                                                                                                                                                                                                         |
| `source_spec_version` | string or null  | no       | —                                                                                                                                                                                                         |
| `source_event_id`     | string or null  | no       | —                                                                                                                                                                                                         |

Status codes:

| Status | Meaning                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                     |
| `401`  | Missing or invalid credentials.                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                              |
| `409`  | Repository identity conflicts with a retained receipt; `detail.code` is `repository_identity_conflict`. No foreign Fact ID is returned. |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.                                                        |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input. |
| `503`  | PostgreSQL Fact store unavailable; the request does not acknowledge successful storage.                                                 |

## POST /v1/logs

**Auth:** Bearer token from the named `SEDIMENT_INGEST_TOKENS` map or the legacy `$SEDIMENT_API_BEARER_TOKEN`. The operator token also permits explicit operator ingest. Missing or invalid credentials return 401; retrieval authority returns 403.

**Response:** Returns `{}` — the empty OTLP/HTTP JSON `ExportLogsServiceResponse`, which means full success. Per-record dedup is invisible to the exporter: a redelivered record is counted in the server log, never reported back.

Status codes:

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                            |
| `400`  | The body is not JSON, or not a JSON object — 400 so the exporter drops it instead of retrying. |
| `401`  | Missing or invalid credentials.                                                                |
| `403`  | The credential lacks the authority required by this route.                                     |
| `413`  | Body over 25 MiB. The cap is enforced pre-auth, on every door that reads a body.               |

## GET /query/evidence

Inventory captured Inference calls without message content or raw payloads.

The complete visible inventory has at most 1,000 calls, 8 MiB of source metadata, and a 1 MiB response. An unknown Session returns `found: false`. Each request checks live scope and Quarantine in one database snapshot.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Returns schema\_version 1, the Session ID, Quarantine revision, found, capture\_completeness=unknown, visible and quarantined Inference call counts, and calls sorted by observation time and Fact ID. Unknown or foreign Sessions return found=false with zero counts. Known empty Sessions return found=true. The inventory excludes message content, raw payloads, and user identifiers. Each request checks live visibility in one read snapshot. The response has Cache-Control: no-store. Limits: 1,000 visible calls, 8 MiB of selected source metadata, and a 1 MiB strict JSON response. IDs travel in query parameters.

Parameters:

| Name         | In    | Type   | Required |
| ------------ | ----- | ------ | -------- |
| `session_id` | query | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                                                                       |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                           |
| `401`  | Missing or invalid credentials.                                                                                                                                                                               |
| `403`  | The credential lacks the authority required by this route.                                                                                                                                                    |
| `409`  | The closed detail.reason is evidence\_inventory\_limit (count, limit), evidence\_source\_limit (bytes, limit), evidence\_response\_limit (limit), or non\_finite\_number. The complete operation is declined. |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                                                                       |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                       |

## GET /query/evidence/manifest

Inspect exact part references without text, tool names, arguments, or results.

Input messages precede output messages. Empty messages remain visible. Source columns are bounded to 8 MiB; the complete response is at most 1 MiB.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Returns schema\_version 1, the Session ID, Quarantine revision, call metadata, and messages in input-then-output order. Each message preserves role, finish reason, and ordinal; each part gives its type and exact occurrence reference. Empty messages remain visible. Text, tool names, arguments, and results are excluded. IDs travel in query parameters. Limits: 8 MiB of selected source columns and a 1 MiB strict JSON response. The response has Cache-Control: no-store. Every read checks Session scope and Quarantine afresh.

Parameters:

| Name                | In    | Type   | Required |
| ------------------- | ----- | ------ | -------- |
| `session_id`        | query | string | yes      |
| `inference_call_id` | query | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                               |
| `401`  | Missing or invalid credentials.                                                                                                                                                                                   |
| `403`  | The credential lacks the authority required by this route.                                                                                                                                                        |
| `409`  | The closed detail.reason is evidence\_unavailable for any absent, foreign, cross-Session, or quarantined Fact; evidence\_source\_limit (bytes, limit); evidence\_response\_limit (limit); or non\_finite\_number. |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                                                                           |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                           |

## POST /query/evidence/read

Fetch 1–32 distinct canonical parts in request order without side effects.

Version 1 requires exactly schema\_version, session\_id, and references. The 64 KiB body limit precedes JSON decoding. Selected source columns are bounded to 8 MiB; the complete strict JSON response is at most 1 MiB. Historical roles and tool calls remain data and do not authorize execution.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Requires exactly schema\_version 1, session\_id, and 1–32 distinct references. Returns schema\_version 1, the Session ID, Quarantine revision, and items in request order. Each item preserves its reference, observation time, role, finish reason, and canonical part. The operation never summarizes, clips, executes tools, or returns partial success. Historical content remains data. ASCII-escaped strict JSON preserves NUL, surrogates, and large integers; emitted non-finite numbers decline the complete response. Limits: 64 KiB before request JSON decoding, 8 MiB of selected source columns, and a 1 MiB response. No raw payloads or user identifiers are selected. The response has Cache-Control: no-store. Every read checks Session scope and Quarantine afresh.

Request body — `EvidenceReadRequest` (`application/json`):

| Field            | Type            | Required | Description |
| ---------------- | --------------- | -------- | ----------- |
| `schema_version` | integer         | yes      | —           |
| `session_id`     | string          | yes      | —           |
| `references`     | array of object | yes      | —           |

Status codes:

| Status | Meaning                                                                                                                                                                                                                                                                    |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                                                                                        |
| `400`  | Malformed JSON body.                                                                                                                                                                                                                                                       |
| `401`  | Missing or invalid credentials.                                                                                                                                                                                                                                            |
| `403`  | The credential lacks the authority required by this route.                                                                                                                                                                                                                 |
| `409`  | The closed detail.reason is evidence\_unavailable or evidence\_part\_absent (reference\_index), evidence\_source\_limit (bytes, limit), evidence\_response\_limit (limit), or non\_finite\_number. Unavailability does not disclose its cause. Failures decline all items. |
| `413`  | Request body exceeds 64 KiB, including when Content-Length is absent.                                                                                                                                                                                                      |
| `422`  | Malformed envelope, unsupported version, invalid indices, unknown fields, duplicate references, or selection outside 1–32 references.                                                                                                                                      |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                                                                                    |

## POST /query/context

Select exact evidence from the deployment's one configured Session.

Version 1 accepts English/code keywords, excludes reasoning, and returns at most eight complete parts within max\_bytes (4–64 KiB; default 16 KiB). Scores count distinct token overlap; capture completeness remains unknown. The operation rechecks Quarantine, persists nothing, and shares the evidence worker admission limit and 30-second deadline.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Accepts schema\_version=1, a nonblank English/code query of at most 2048 UTF-8 bytes with a meaningful token, and optional integer max\_bytes (4096–65536; default 16384). Rejects all other fields. Returns policy/schema version 1, source\_session\_id, quarantine\_revision, matched/no\_match/budget\_exhausted status, unknown capture completeness, complete visible scan coverage, closed exclusion counts, and at most eight scored exact EvidenceReadItem values. Each item retains its occurrence reference, timestamp, role, finish\_reason, and complete canonical part. Scores count distinct token overlap. Whole-response ASCII JSON respects max\_bytes and carries Cache-Control: no-store. Reads stream one call at a time in one snapshot: at most 1000 visible calls, 64 MiB selected stored columns, 8 MiB per row, 8 MiB scan metadata, and 16384 parts. Selection reserves at most 32 MiB of candidate state; this is not a process-memory bound. Reasoning and non-finite parts are counted exclusions.

Request body — `ContextRetrievalRequest` (`application/json`):

| Field            | Type    | Required | Description     |
| ---------------- | ------- | -------- | --------------- |
| `schema_version` | integer | yes      | —               |
| `query`          | string  | yes      | —               |
| `max_bytes`      | integer | no       | default `16384` |

Status codes:

| Status | Meaning                                                                                                                                                                                                                                                                                                                |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                                                                                                                                    |
| `400`  | Malformed JSON body.                                                                                                                                                                                                                                                                                                   |
| `401`  | Missing or invalid credentials.                                                                                                                                                                                                                                                                                        |
| `403`  | The credential lacks the authority required by this route.                                                                                                                                                                                                                                                             |
| `404`  | Retrieval is disabled or plural configuration requires explicit Session selection.                                                                                                                                                                                                                                     |
| `409`  | Closed detail.reason: evidence\_unavailable, evidence\_inventory\_limit (count, limit), evidence\_source\_limit (bytes, limit), retrieval\_part\_limit (count, limit), retrieval\_state\_limit (limit\_bytes; no partial counts), evidence\_response\_limit (limit), or non\_finite\_number. No partial scan succeeds. |
| `413`  | The streamed body exceeds 16 KiB before JSON decoding.                                                                                                                                                                                                                                                                 |
| `422`  | Invalid version, query, byte budget, or undeclared field; content is omitted.                                                                                                                                                                                                                                          |
| `503`  | The shared read pool is full, the 30-second deadline expires, or PostgreSQL is unavailable.                                                                                                                                                                                                                            |

## POST /query/context/discover

Find at most eight Sessions within the deployment's explicit grant.

Version 1 searches English/code keywords under aggregate source bounds. An optional provider/host/repository-ID/SHA anchor prioritizes directly observed commit relationships. Each candidate carries exact evidence or an observed commit witness. Discovery persists nothing and grants no access.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Accepts schema\_version=1, query and optional max\_bytes with the fixed retrieval bounds, and an optional complete commit anchor (repository\_provider, repository\_host, repository\_id, commit\_sha). Returns policy/schema version 1, quarantine\_revision, the anchor or null, unknown capture completeness, matched/no\_match/budget\_exhausted status, complete coverage, closed part/Session exclusion counts, and at most eight candidate Sessions. Each has session\_id, score, matched\_parts, an exact EvidenceReadItem preview or null, and commit\_match (observation\_id, source\_push\_id, captured\_at) or null. Commit matches require a visible exact source Push with equal provider identity. Complete visible source limits of 1000 calls, 64 MiB selected stored columns, 8 MiB per row, 8 MiB scan metadata, and 16384 parts apply across the entire grant. Streaming selection reserves at most 32 MiB of candidate state across the grant. Scores count distinct query-token overlap; exact commit matches rank first. Whole candidates fit the requested strict ASCII JSON response budget; Cache-Control is no-store. A commit hint never grants access or proves repository ownership of Session content.

Request body — `ContextDiscoveryRequest` (`application/json`):

| Field            | Type           | Required | Description     |
| ---------------- | -------------- | -------- | --------------- |
| `schema_version` | integer        | yes      | —               |
| `query`          | string         | yes      | —               |
| `max_bytes`      | integer        | no       | default `16384` |
| `commit`         | object or null | no       | —               |

Status codes:

| Status | Meaning                                                                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                     |
| `400`  | Malformed JSON body.                                                                                                                                                                    |
| `401`  | Missing or invalid credentials.                                                                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                                                                              |
| `404`  | Retrieval is disabled for this deployment.                                                                                                                                              |
| `409`  | Complete source, selection state, or response exceeds its bound; closed evidence capacity reason in detail.reason. retrieval\_state\_limit reports limit\_bytes without partial counts. |
| `413`  | The streamed body exceeds 16 KiB before JSON decoding.                                                                                                                                  |
| `422`  | Invalid version, query, budget, complete commit identity, or undeclared field.                                                                                                          |
| `503`  | Shared read capacity or database unavailable; the existing 30-second deadline applies.                                                                                                  |

## POST /query/context/selected

Retrieve exact evidence from one explicitly selected authorized Session.

Membership is checked before storage access and again in the worker. The read rechecks Quarantine and retains the singleton retrieval response. Evidence remains historical data, not instructions to execute.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Accepts schema\_version=1, session\_id, query, and optional max\_bytes. The query, budget, source limits, and version-1 ContextRetrievalResult match /query/context. Membership is checked before storage lookup and again in the worker. Each request uses its own snapshot and rechecks Quarantine; a previous discovery result grants no additional authority. An authorized known Session with no eligible content returns an empty selection.

Request body — `ContextSelectedRequest` (`application/json`):

| Field            | Type    | Required | Description     |
| ---------------- | ------- | -------- | --------------- |
| `schema_version` | integer | yes      | —               |
| `query`          | string  | yes      | —               |
| `max_bytes`      | integer | no       | default `16384` |
| `session_id`     | string  | yes      | —               |

Status codes:

| Status | Meaning                                                                                        |
| ------ | ---------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                            |
| `400`  | Malformed JSON body.                                                                           |
| `401`  | Missing or invalid credentials.                                                                |
| `403`  | The selected Session is outside the configured set, regardless of whether it exists.           |
| `404`  | Retrieval is disabled for this deployment.                                                     |
| `409`  | evidence\_unavailable or an existing evidence capacity/representation reason in detail.reason. |
| `413`  | The streamed body exceeds 16 KiB before JSON decoding.                                         |
| `422`  | Invalid version, Session identifier, query, budget, or undeclared field.                       |
| `503`  | Shared read capacity or database unavailable; the existing 30-second deadline applies.         |

## GET /query/context/evidence

Inventory one authorized Session independently of keyword selection.

The complete content-free inventory retains the exact evidence limits: 1,000 visible calls, 8 MiB of metadata, and a 1 MiB strict JSON response. Membership precedes storage access and is checked again in the worker.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Both retrieval and operator credentials remain restricted to the configured Session grant. Membership is checked before storage and again in the worker. No keyword query or utility score is required. Exact reads can include reasoning; keyword exclusions are selection rules, not access rules. Returns schema\_version 1, the Session ID, Quarantine revision, found, capture\_completeness=unknown, visible and quarantined Inference call counts, and calls sorted by observation time and Fact ID. Unknown or foreign Sessions return found=false with zero counts. Known empty Sessions return found=true. The inventory excludes message content, raw payloads, and user identifiers. Each request checks live visibility in one read snapshot. The response has Cache-Control: no-store. Limits: 1,000 visible calls, 8 MiB of selected source metadata, and a 1 MiB strict JSON response. IDs travel in query parameters.

Parameters:

| Name         | In    | Type   | Required |
| ------------ | ----- | ------ | -------- |
| `session_id` | query | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                                                                       |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                           |
| `401`  | Missing or invalid credentials.                                                                                                                                                                               |
| `403`  | Session outside the configured grant, regardless of existence.                                                                                                                                                |
| `404`  | Context retrieval is disabled for this deployment.                                                                                                                                                            |
| `409`  | The closed detail.reason is evidence\_inventory\_limit (count, limit), evidence\_source\_limit (bytes, limit), evidence\_response\_limit (limit), or non\_finite\_number. The complete operation is declined. |
| `422`  | Invalid exact evidence request; caller-supplied values and field names are omitted.                                                                                                                           |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                       |

## GET /query/context/evidence/manifest

Describe exact part references in one authorized Session.

Content and raw payloads remain absent. Source columns are bounded to 8 MiB and the complete response to 1 MiB. Each read rechecks Quarantine.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Both retrieval and operator credentials remain restricted to the configured Session grant. Membership is checked before storage and again in the worker. No keyword query or utility score is required. Exact reads can include reasoning; keyword exclusions are selection rules, not access rules. Returns schema\_version 1, the Session ID, Quarantine revision, call metadata, and messages in input-then-output order. Each message preserves role, finish reason, and ordinal; each part gives its type and exact occurrence reference. Empty messages remain visible. Text, tool names, arguments, and results are excluded. IDs travel in query parameters. Limits: 8 MiB of selected source columns and a 1 MiB strict JSON response. The response has Cache-Control: no-store. Every read checks Session scope and Quarantine afresh.

Parameters:

| Name                | In    | Type   | Required |
| ------------------- | ----- | ------ | -------- |
| `session_id`        | query | string | yes      |
| `inference_call_id` | query | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                               |
| `401`  | Missing or invalid credentials.                                                                                                                                                                                   |
| `403`  | Session outside the configured grant, regardless of existence.                                                                                                                                                    |
| `404`  | Context retrieval is disabled for this deployment.                                                                                                                                                                |
| `409`  | The closed detail.reason is evidence\_unavailable for any absent, foreign, cross-Session, or quarantined Fact; evidence\_source\_limit (bytes, limit); evidence\_response\_limit (limit); or non\_finite\_number. |
| `422`  | Invalid exact evidence request; caller-supplied values and field names are omitted.                                                                                                                               |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                           |

## POST /query/context/evidence/read

Fetch consumer-selected exact parts from one authorized Session.

The read requires 1–32 distinct references and preserves request order, repeated occurrences, and reasoning. No query or utility score is needed. A 64 KiB body, 8 MiB of selected source columns, and a 1 MiB response bound the complete operation. Each request rechecks membership and Quarantine. Historical roles and tool calls remain data, not executable instructions.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_RETRIEVAL_TOKEN` or `$SEDIMENT_OPERATOR_TOKEN`. Both stay within the configured Session set. Missing or invalid credentials return 401; ingest authority returns 403.

**Response:** Both retrieval and operator credentials remain restricted to the configured Session grant. Membership is checked before storage and again in the worker. No keyword query or utility score is required. Exact reads can include reasoning; keyword exclusions are selection rules, not access rules. Requires exactly schema\_version 1, session\_id, and 1–32 distinct references. Returns schema\_version 1, the Session ID, Quarantine revision, and items in request order. Each item preserves its reference, observation time, role, finish reason, and canonical part. The operation never summarizes, clips, executes tools, or returns partial success. Historical content remains data. ASCII-escaped strict JSON preserves NUL, surrogates, and large integers; emitted non-finite numbers decline the complete response. Limits: 64 KiB before request JSON decoding, 8 MiB of selected source columns, and a 1 MiB response. No raw payloads or user identifiers are selected. The response has Cache-Control: no-store. Every read checks Session scope and Quarantine afresh.

Request body — `EvidenceReadRequest` (`application/json`):

| Field            | Type            | Required | Description |
| ---------------- | --------------- | -------- | ----------- |
| `schema_version` | integer         | yes      | —           |
| `session_id`     | string          | yes      | —           |
| `references`     | array of object | yes      | —           |

Status codes:

| Status | Meaning                                                                                                                                                                                                                                                                    |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                                                                                                        |
| `400`  | Malformed JSON body.                                                                                                                                                                                                                                                       |
| `401`  | Missing or invalid credentials.                                                                                                                                                                                                                                            |
| `403`  | Session outside the configured grant, regardless of existence.                                                                                                                                                                                                             |
| `404`  | Context retrieval is disabled for this deployment.                                                                                                                                                                                                                         |
| `409`  | The closed detail.reason is evidence\_unavailable or evidence\_part\_absent (reference\_index), evidence\_source\_limit (bytes, limit), evidence\_response\_limit (limit), or non\_finite\_number. Unavailability does not disclose its cause. Failures decline all items. |
| `413`  | Request body exceeds 64 KiB, including when Content-Length is absent.                                                                                                                                                                                                      |
| `422`  | Invalid exact evidence request; caller-supplied values and field names are omitted.                                                                                                                                                                                        |
| `503`  | Evidence shares both query/report slots; reports have no reserved slot. Busy workers, a 30-second deadline, or unavailable PostgreSQL decline the read.                                                                                                                    |

## GET /query/ci/outcome

Return one exact CI run receipt; ambiguous forge namespaces require a selector.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Returns one metadata-only CI outcome and a commit-query path bound to its identity and evidence boundary. Multiple forge namespaces require a complete repository provider/host/ID selector. An unknown identity returns 200 `{"found": false}` without disclosing another organization's rows.

Parameters:

| Name                  | In    | Type            | Required |
| --------------------- | ----- | --------------- | -------- |
| `provider`            | query | string          | yes      |
| `run_id`              | query | string          | yes      |
| `run_attempt`         | query | integer or null | no       |
| `repo`                | query | string or null  | no       |
| `repository_provider` | query | string or null  | no       |
| `repository_host`     | query | string or null  | no       |
| `repository_id`       | query | string or null  | no       |
| `as_of`               | query | string or null  | no       |

Status codes:

| Status | Meaning                                                                                                                                                                       |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                           |
| `401`  | Missing or invalid credentials.                                                                                                                                               |
| `403`  | The credential lacks the authority required by this route.                                                                                                                    |
| `409`  | The closed `detail.reason` is `repository_selector_ambiguous`, `repository_evidence_limit`, or `non_finite_number`. No partial result is emitted; stored Facts remain intact. |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                                       |
| `503`  | Worker capacity, deadline, result limit, or database availability prevents this operation; retry retained request bytes after recovery.                                       |

## GET /query/ci/failures

Page exact CI receipts under one repository identity and historical boundary.

The default identity boundary is `captured_before`. Capture bounds remain half-open; an explicit `as_of` adds an inclusive evidence ceiling. Cursors bind organization, qualified repository, boundary, filters, and quarantine revision. They don't preserve a database transaction between requests.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Returns one keyset-paginated page for a repository and capture-time window. The normalized result defaults to `failed`; callers can request another result for comparison. Each row links to its commit query with the same identity and boundary. The default `as_of` is `captured_before`; an explicit boundary is inclusive. Cursors bind the organization, qualified repository, boundary, filters, and quarantine revision. They don't retain a transaction between requests.

Parameters:

| Name                  | In    | Type            | Required |
| --------------------- | ----- | --------------- | -------- |
| `captured_after`      | query | string          | yes      |
| `captured_before`     | query | string          | yes      |
| `repo`                | query | string or null  | no       |
| `repository_provider` | query | string or null  | no       |
| `repository_host`     | query | string or null  | no       |
| `repository_id`       | query | string or null  | no       |
| `as_of`               | query | string or null  | no       |
| `result`              | query | string          | no       |
| `workflow_name`       | query | string or null  | no       |
| `pr_number`           | query | integer or null | no       |
| `limit`               | query | integer         | no       |
| `cursor`              | query | string or null  | no       |

Status codes:

| Status | Meaning                                                                                                                                                                                         |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                             |
| `401`  | Missing or invalid credentials.                                                                                                                                                                 |
| `403`  | The credential lacks the authority required by this route.                                                                                                                                      |
| `409`  | The closed `detail.reason` is `repository_selector_ambiguous`, `repository_evidence_limit`, or `non_finite_number`. No partial result is emitted; stored Facts remain intact.                   |
| `422`  | Required bounds are absent or invalid, the start doesn't precede the end, identity is incomplete, a supplied name contradicts the selected identity, or the cursor no longer matches its scope. |
| `503`  | Worker capacity, deadline, result limit, or database availability prevents this operation; retry retained request bytes after recovery.                                                         |

## GET /query/session/\{session\_id}

Return one bounded, metadata-only Session evidence dossier.

Observation-backed commit edges keep `attribution_sources` empty. Similarity extrema and `attributed_files` are unavailable and omitted from JSON.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Returns a bounded timeline, visible and quarantined counts, capture gaps, captured Session commit observations, exact-head Push receipts, and matching CI outcomes under one complete repository context. Repository identity accompanies each delivery summary; `repository_skipped` counts declined observation sources. Captured content, user identity, file paths, and the free-form CI reason remain absent. An unknown Session returns 200 `{"found": false}`.

Parameters:

| Name         | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `session_id` | path | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                                 |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                     |
| `401`  | Missing or invalid credentials.                                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                                              |
| `409`  | Emitted content contains a non-finite number (`detail.reason=non_finite_number`), or the Session or its linked delivery evidence exceeds the fixed cap. |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input.                 |
| `503`  | The bounded read worker is busy, exceeds its 30-second deadline or result limit, or cannot access PostgreSQL.                                           |

## GET /query/commit/\{sha}

Investigate exact commit evidence in separate repository lifetimes.

Captured observations establish Session associations. Call-to-file Attribution remains inferred. Optional repository selectors and an inclusive `as_of` bound all supporting evidence; otherwise one request instant supplies the bound. A bounded child process owns the Derivation and its database connection. Capacity and execution deadlines return 503 after process cleanup.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** Observed Session edges, inferred calls and decisions, and exact CI Facts, grouped by repository lifetime with identity and observed names. Unresolved CI remains separate; declined source counts stay visible. Select with a complete provider/host/ID triple or an unambiguous name. An inclusive `as_of` bounds all supporting evidence. No evidence returns `{"commit_sha": "<sha>", "attributed": false}` at 200, not an error. The derivation runs per request and is never persisted (ADR 0001).

Parameters:

| Name                  | In    | Type           | Required |
| --------------------- | ----- | -------------- | -------- |
| `sha`                 | path  | string         | yes      |
| `repo`                | query | string or null | no       |
| `repository_provider` | query | string or null | no       |
| `repository_host`     | query | string or null | no       |
| `repository_id`       | query | string or null | no       |
| `as_of`               | query | string or null | no       |

Status codes:

| Status | Meaning                                                                                                                                                                                  |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                                                                      |
| `401`  | Missing or invalid credentials.                                                                                                                                                          |
| `403`  | The credential lacks the authority required by this route.                                                                                                                               |
| `409`  | The closed `detail.reason` is `repository_selector_ambiguous`, `repository_evidence_limit`, or `non_finite_number`. No partial result is emitted; stored Facts remain intact.            |
| `422`  | Invalid SHA, incomplete identity, or a supplied name that contradicts the selected identity.                                                                                             |
| `503`  | The bounded read worker is busy, exceeds its 30-second deadline or result limit, or cannot access PostgreSQL. It runs off the event loop, so the ingest doors stay responsive meanwhile. |

## GET /v1/me

Auth probe for `sediment login`: the deployment's tenant and the API version, reported verbatim so the client can detect skew.

**Auth:** Any configured bearer authority. The response identifies the configured authority and client, never the token. Missing or invalid credentials return 401.

**Response:** `{"org_id": "<tenant>", "version": "<api version>", "authority": "<ingest, operator, or retrieval>", "client_id": "<configured client>"}`. Retrieval authority also receives source\_session\_id under singleton configuration or sorted source\_session\_ids under plural configuration. These identifiers never select tenancy.

Status codes:

| Status | Meaning                             |
| ------ | ----------------------------------- |
| `200`  | Success — the response shape above. |
| `401`  | Missing or invalid credentials.     |

## GET /v1/facts

One entry per `FactTable`: total rows and the derivation-facing ("visible" = not quarantined) count. Sessions are upserted metadata, not quarantinable facts, so they carry a bare count with no visible column — the same shape `sediment facts` prints.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** `{"sessions": <int>, "tables": {"<table>": {"total": <int>, "visible": <int>}}, "quarantine_revision": <int>}`. `quarantine_revision` is the org's provenance token: the numeric quarantine-log high-water mark, `0` when nothing is quarantined.

Status codes:

| Status | Meaning                                                    |
| ------ | ---------------------------------------------------------- |
| `200`  | Success — the response shape above.                        |
| `401`  | Missing or invalid credentials.                            |
| `403`  | The credential lacks the authority required by this route. |

## GET /v1/facts/session/\{session\_id}

Fact counts for one session, so a client can verify its own writes without treating unrelated organization-wide totals as evidence.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** `{"session_id": "<session id>", "tables": {"<session table>": {"total": <int>, "visible": <int>}}}`. The tables are inference calls, developer decisions, edit observations, rejected edits, and retry linkages. The demo command uses these counts so unrelated organization-wide facts cannot mask a dropped demo record.

Parameters:

| Name         | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `session_id` | path | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                     |
| `401`  | Missing or invalid credentials.                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                              |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input. |

## GET /v1/facts/session/\{session\_id}/inference-calls

Return the narrow fields needed to reconcile one Session's usage.

Prompts, responses, raw provider payloads, and user identity stay absent.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** `{"session_id": "<session id>", "inference_calls": [{"inference_call_id": "<id>", "model_call_id": "<id or null>", "gateway_provider": "<provider>", "model_provider": "<provider or null>", "model": "<model>", "input_tokens": <int or null>, "output_tokens": <int or null>, "duration_ms": <int or null>}]}`. Prompts, responses, raw provider payloads, and user identity are absent.

Parameters:

| Name         | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `session_id` | path | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                     |
| `401`  | Missing or invalid credentials.                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                              |
| `409`  | The Session exceeds the bounded reconciliation read.                                                                                    |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input. |

## GET /v1/facts/session/\{session\_id}/compatibility-evidence

Return bounded decision, Edit observation, and inference join fields.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** `{"session_id": "<session id>", "inference_calls": [{"tool_call_ids": ["<response tool-call id>"]}], "developer_decisions": [{"agent_harness": "<harness>", "accepted": <bool>, "explicit": <bool>, "interaction_mode": "<mode>", "call_id": "<id or null>"}], "edit_observations": [{"agent_harness": "<harness>", "call_id": "<id>"}]}`. Captured content, raw payloads, paths, user identity, and Fact identifiers are absent.

Parameters:

| Name         | In   | Type   | Required |
| ------------ | ---- | ------ | -------- |
| `session_id` | path | string | yes      |

Status codes:

| Status | Meaning                                                                                                                                 |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                                                     |
| `401`  | Missing or invalid credentials.                                                                                                         |
| `403`  | The credential lacks the authority required by this route.                                                                              |
| `409`  | The Session exceeds a bounded evidence read.                                                                                            |
| `422`  | A required header, path parameter, or body field failed validation. The response carries `type`/`loc`/`msg` and never echoes the input. |

## GET /v1/reports/model-outcomes

Return a bounded model-outcome report.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** A version 1 envelope containing the explicit report scope and the canonical base model-outcome report. The route uses the deployment org and doesn't persist Derivation output.

Parameters:

| Name           | In    | Type   | Required |
| -------------- | ----- | ------ | -------- |
| `cohort_start` | query | string | yes      |
| `cohort_end`   | query | string | yes      |
| `as_of`        | query | string | yes      |

Status codes:

| Status | Meaning                                                                                             |
| ------ | --------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                 |
| `401`  | Missing or invalid credentials.                                                                     |
| `403`  | The credential lacks the authority required by this route.                                          |
| `409`  | The cohort, supporting Fact population, or serialized response exceeds its fixed cap.               |
| `422`  | A bound is absent or invalid, or the half-open cohort exceeds 31 days.                              |
| `503`  | The bounded read worker is busy, exceeds its deadline or result limit, or cannot access PostgreSQL. |

## GET /v1/reports/accepted-work-lifecycle

Return a bounded accepted-work lifecycle report.

**Auth:** Bearer token — `Authorization: Bearer $SEDIMENT_OPERATOR_TOKEN`. Missing or invalid credentials return 401; ingest or retrieval authority returns 403.

**Response:** A version 1 envelope containing the explicit report scope and the canonical accepted-work lifecycle report. The route uses the deployment org and doesn't persist Derivation output.

Parameters:

| Name           | In    | Type   | Required |
| -------------- | ----- | ------ | -------- |
| `cohort_start` | query | string | yes      |
| `cohort_end`   | query | string | yes      |
| `as_of`        | query | string | yes      |

Status codes:

| Status | Meaning                                                                                             |
| ------ | --------------------------------------------------------------------------------------------------- |
| `200`  | Success — the response shape above.                                                                 |
| `401`  | Missing or invalid credentials.                                                                     |
| `403`  | The credential lacks the authority required by this route.                                          |
| `409`  | The cohort, supporting Fact population, or serialized response exceeds its fixed cap.               |
| `422`  | A bound is absent or invalid, or the half-open cohort exceeds 31 days.                              |
| `503`  | The bounded read worker is busy, exceeds its deadline or result limit, or cannot access PostgreSQL. |

## GET /health

**Auth:** None — the liveness probe is unauthenticated.

**Response:** `{"status": "ok", "version": "<api version>"}`.

Status codes:

| Status | Meaning                             |
| ------ | ----------------------------------- |
| `200`  | Success — the response shape above. |
