The API
The API is a FastAPI service at https://api.stratl.ai (or http://localhost:8000). Its OpenAPI description is served at /openapi.json, and the reference pages on this site are generated from it, so they are exactly as complete as the service.
Authentication
Section titled “Authentication”Two kinds of caller.
People sign in through the portal and hold a session cookie. The portal forwards /api to the API server-side so the cookie stays first-party; a browser never calls the API origin directly.
Agents and collectors send an ingest key: Authorization: Bearer sk_stratl_.... Ingest keys may write records and upload originals (records:write) and nothing else. They are created and revoked under Settings → API keys, shown once, and stored as hashes.
Every request is scoped to the caller’s workspace. A record, bundle, notice, source or hold that belongs to another workspace answers 404, the same as one that does not exist. Roles decide what a person may change; the server enforces the matrix on every write route. Roles.
Errors
Section titled “Errors”Errors are JSON with a detail object carrying a machine-readable code and, sometimes, more:
{ "detail": { "code": "notice_not_approved", "status": "draft" } }| Status | Typical codes |
|---|---|
| 401 | not_authenticated |
| 403 | read_only_role (an auditor tried to change something), forbidden with permission |
| 404 | decision_not_found, notice_not_found, subject_not_found, key_not_found: also the answer for another workspace’s objects |
| 409 | decision_id_conflict (the id exists in another workspace), notice_not_approved, custody_already_taken, hold_already_lifted |
| 413 | artifact_too_large (default limit 5 MiB) |
| 422 | Validation errors, hash_mismatch on an artifact upload, recipient_email_required, custody_probe_failed with the probe steps |
| 429 | Sign-in code rate limits, with retry_in |
| 502 | email_failed: the email provider refused a notice |
Endpoint families
Section titled “Endpoint families”| Family | Prefix | What |
|---|---|---|
| Auth | /v1/auth/… |
Codes, sessions, workspace creation, API keys, members, invitations, switching |
| Ingest | /v1/ingest/srf, /v1/ingest/otlp/v1/traces |
Records in, from SDKs or collectors. Idempotent on decision_id |
| Artifacts | /v1/artifacts/… |
Content-addressed originals: check which fingerprints are missing, PUT bytes whose hash must match the path, GET them back |
| Index | /v1/decisions, /v1/subjects, /v1/sources, /v1/stats |
Search and read. Every record carries its verification and its retention state |
| Evidence | …/bundle, …/pack |
The bundle for a record and the pack for a subject |
| Custody | /v1/custody/…, /v1/keys/{key_id} |
Status, checkpoints, labels, providers, the probe and taking custody; public keys without auth |
| Packs and reports | /v1/packs, …/coverage, /v1/reports/period |
Framework coverage per record and per period |
| Notices | …/notices, /v1/notices/…, …/reconsideration, …/related |
The notice lifecycle and reconsiderations |
| Retention | /v1/retention, /v1/holds |
The policy, what is eligible for deletion, and legal holds |
| Connectors | /v1/connectors/… |
Pull connectors and their runs |
Reads use limit and offset; the decision list accepts filters (q, subject_type, subject_id, agent_id, source, assurance, adverse).
Keeping the reference current
Section titled “Keeping the reference current”make openapi in the backend exports the running service’s description into this repository at openapi/stratl.json; the reference pages rebuild from it. Maintaining these docs.