OpenAPI Reference
packages/contracts holds 53 OpenAPI 3.1 documents — one per domain — and
contracts/asyncapi holds 45 AsyncAPI documents for the event surface. They are the
canonical description of the API; this page lists two of them as a worked introduction and
does not attempt to reproduce the rest.
The Animal Digital Passport API is packages/contracts/openapi.animals.yaml.
Endpoints (v1)
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/animals | Create an animal passport |
| GET | /v1/animals/{id} | Private identity view (authorized) |
| PATCH | /v1/animals/{id} | Partial update |
| GET / POST | /v1/animals/{id}/delegates | List / grant delegation |
| DELETE | /v1/animals/{id}/delegates/{delegateId} | Revoke delegation |
| PUT | /v1/animals/{id}/emergency-profile | Create/replace emergency profile |
| GET / POST | /v1/animals/{id}/photos | List / register photo metadata |
| GET | /v1/emergency/{token} | Public QR emergency view (unauthenticated) |
| GET | /healthz /readyz | Liveness / readiness |
Safety & Recovery (v1) — packages/contracts/openapi.safety.yaml
| Method | Path | Auth | Purpose |
|---|---|---|---|
| POST | /v1/safety/lost-reports | yes | Report an animal lost |
| GET | /v1/safety/lost-reports/{id} | yes | Private full view (precise location) |
| POST | /v1/safety/lost-reports/{id}/resolve | yes | Recovery workflow |
| POST | /v1/safety/lost-reports/{id}/sightings | yes | Submit a sighting |
| POST | /v1/safety/found-reports | yes | Report a found animal |
| POST | /v1/safety/found-reports/{id}/match | yes | Candidate lost reports (scored) |
| GET | /v1/safety/alerts?lat=&lng=&radius= | no | Nearby public alerts (coarsened) |
| GET | /v1/safety/alerts/{id} | no | Public alert view |
| GET | /v1/safety/alerts/{id}/sightings | no | Public sightings list |
Academy credentials (v1) — public, unauthenticated
Four routes serve a third-party wallet or an employer's checker everything it needs to verify an Open Badges 3.0 credential offline, without Buddora's cooperation beyond serving bytes (ADR-029). None of them reads a learner record, an enrolment, a score or an attempt.
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/certificates/{code}/credential | the signed Open Badges 3.0 AchievementCredential |
| GET | /v1/certificates/{code}/accreditation | what it may claim, and where to check it |
| GET | /v1/credentials/issuers/{orgId} | the issuer profile carrying the public key |
| GET | /v1/credentials/status-lists/{orgId}/{page} | the signed W3C Bitstring Status List (revocation) |
A public key nobody can fetch verifies nothing, and a status list behind authentication would make revocation invisible to exactly the strangers revocation exists to protect — hence all four being public. The credential route carries the same per-IP throttle as the verification lookup, because it resolves the same 256-bit code and does strictly more work per request.
Credentials are minted on demand and never stored, so a badge fetched today claims what is
recorded today. A badge already in a wallet keeps claiming what it claimed — inherent to signed
credentials, mitigated by the alignment carrying its own validity window, a credentialStatus
and an evidence link back to the live record.
Authentication
Bearer OIDC access token (Keycloak) in production, via authorization code + PKCE. PKCE
S256 is enforced at the realm as of 2026-08-28, and the resource-owner password grant
(ROPC) is disabled — see Security Baseline.
In development the API accepts an X-Debug-Actor header — only when API_ENV=development;
the API refuses to start otherwise.