HTTP API

The backend serves a JSON HTTP API under /api/v1. This page documents the API, rendered from the OpenAPI document that the FastAPI application itself generates. Narrative pages for the Python side live in Python API reference.

Conventions

Base path

All catalog routes are below /api/v1. /healthz is the only unversioned route and is public.

Authentication

Every /api/v1 route needs an Authorization: Bearer <token> header. In production the token is an RS256 JWT from the configured OIDC provider; with dev auth enabled, an HS256 token minted with task mint-dev-token is accepted as well. See app.auth.tokens. Without any configured validator, every /api/v1 route answers 503.

Push tokens

Candidate intake (/api/v1/candidates) is the exception. It accepts only the per-registration CI push token, never an OIDC or dev token, and a push token grants no read access. See app.auth.push.

Errors

Errors are JSON objects {"detail": "<message>"}. Errors that carry a machine-readable reason add "code"; recovery advice adds "hint", and some errors add further members, such as the issues list of a refused candidate. The status code of each error class is registered in app.errors.

Interactive docs

A running instance serves Swagger UI at /api/docs and the raw OpenAPI document at /openapi.json. Both are public and contain no catalog data.

The dev-only routes (/auth/dev/token and /auth/dev/roles) are mounted only when dev auth is enabled and are therefore not part of the reference below.

Endpoints

The reference is generated at build time by docs/conf.py and grouped by tag.

default

GET /healthz

Healthz

Report application, database and configuration health.

Returns HTTP 200 with status: ok when the database is reachable, or HTTP 503 with status: degraded otherwise. The config, policy and registrations keys report the configuration loaded at startup.

Parameters:
  • response – Outgoing response, used to set the status code.

  • db – Request-scoped database session.

  • runtime – Startup state of the catalog.

  • settings – Application settings (auth status).

Returns:

A mapping with status, database, config, policy, registrations, rbac, auth and version keys.

Status Codes:
  • 200 OK – Successful Response

me

GET /api/v1/me

Get Me

Describe the caller.

Parameters:
  • principal – The authenticated caller.

  • permissions – The caller’s permissions.

  • runtime – Startup state (approval policy).

Returns:

Identity, permissions and reviewer eligibility.

Status Codes:
  • 200 OK – Successful Response

records

GET /api/v1/records

List Records

Search the catalog with the Phase 1 filters.

Parameters:
  • q – Free text (titles, bodies, UUIDs, paths); blank or omitted matches everything.

  • source – Restrict to one registration id.

  • project – Restrict to one project path.

  • state – Restrict to published or candidate.

  • needs_approval – Restrict to records that need approval.

  • record_type – Decisions (default), errata, or both.

  • sort – Result order, or omitted for the default.

  • page – 1-based page number.

  • page_size – Page size, 1 to MAX_PAGE_SIZE.

  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state.

Returns:

The page.

Query Parameters:
  • q ({'null', 'string'}) – Free text search.

  • source ({'null', 'string'}) – Registration id.

  • project ({'null', 'string'}) – Project path.

  • state ({'null', 'string'}) – state

  • needs_approval (boolean) – Only records whose current content does not satisfy the policy: pending, rejected, changed since acceptance, or policy missing.

  • record_type (string) – Which records to return: decision (default), erratum, or all. Combines with every other filter.

  • sort ({'null', 'string'}) – Result order: relevance (text rank, best first), title (A-Z) or recent (content last changed, newest first). Default: relevance when q is set, else title; relevance without q falls back to title. Ties are broken by title, then id.

  • page (integer)

  • page_size (integer)

Status Codes:
GET /api/v1/records/{record_id}

Get Record

Fetch one record’s detail page.

approval.can_decide (and the blocked reason) is evaluated for the caller.

Parameters:
  • record_id (string) – Record id.

  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state.

  • settings – Application settings (for the stale threshold).

  • principal – The authenticated caller.

  • record_id

Returns:

The detail.

Raises app.errors.NotFoundError:

If the record does not exist.

Status Codes:
GET /api/v1/records/{record_id}/diff

Get Record Diff

Diff two stored snapshots of the record’s identity.

Only digests related to the record are accepted (404 unknown_revision otherwise); see app.services.diff.

Parameters:
  • record_id (string) – Record id.

  • from_digest – Base digest (query from).

  • to_digest – Target digest (query to).

  • provider – Storage provider (overridden by tests).

  • record_id

Returns:

The diff, or base: null with reason: "no_prior_revision".

Query Parameters:
  • from ({'null', 'string'}) – Base digest; default: last decided snapshot, else the previous revision.

  • to ({'null', 'string'}) – Target digest; default: the current digest.

Status Codes:

sources

GET /api/v1/sources

List Sources

List every stored source registration.

Parameters:
  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state.

  • settings – Application settings (for the stale threshold).

Returns:

One entry per stored registration, ordered by id.

Status Codes:
  • 200 OK – Successful Response

POST /api/v1/sources/poll

Poll All Sources

Poll every pollable registration in the background.

Parameters:
  • background – Background task queue.

  • principal – The operator (operate permission).

  • runtime – Startup state.

  • provider – Storage provider (overridden by tests).

Returns:

The accepted ids (HTTP 202).

Raises app.errors.ConflictError:

If nothing is pollable.

Status Codes:
POST /api/v1/sources/{source_id}/poll

Poll One Source

Poll one registration in the background.

Parameters:
  • source_id (string) – Registration id.

  • background – Background task queue.

  • principal – The operator (operate permission).

  • runtime – Startup state.

  • provider – Storage provider (overridden by tests).

  • source_id

Returns:

The accepted id (HTTP 202).

Raises app.errors.NotFoundError:

If the id is not configured.

Raises app.errors.ConflictError:

If it cannot be polled.

Status Codes:

facets

GET /api/v1/facets

Get Facets

List sources and their projects with record counts.

Parameters:
  • provider – Storage provider (overridden by tests).

Returns:

The facets.

Status Codes:
  • 200 OK – Successful Response

decisions

POST /api/v1/records/{record_id}/decisions

Post Decision

Record an accept/reject decision for the record’s current digest.

Parameters:
  • record_id (string) – Record id.

  • body – Action, optional comment and expected digest.

  • principal – The authenticated caller (read required).

  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state (approval policy).

  • record_id

Returns:

The stored event.

Status Codes:

candidates

PUT /api/v1/candidates

Put Candidate

Create or replace the candidate for (source, project, ADR, ref).

Parameters:
  • request – The request.

  • response – The response.

  • credentials – Push-token bearer credentials.

  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state.

Returns:

Record id, server digest, issues and catalog path.

Status Codes:
POST /api/v1/candidates

Post Candidate

Create a candidate; 409 candidate_exists if it already exists.

Parameters:
  • request – The request.

  • response – The response.

  • credentials – Push-token bearer credentials.

  • provider – Storage provider (overridden by tests).

  • runtime – Startup configuration state.

Returns:

Record id, server digest, issues and catalog path.

Status Codes: