REST API
OrbitalReg's HTTP API is REST-shaped JSON-over-HTTPS. Every resource admits standard list / read / create / update / delete operations, and every governance change goes through audit logging.
The API is versioned at the path layer (/api/v1/…, /api/v2/…). Within a major, every minor release is forward-compatible — new fields are additive, never removing an existing one.
This page is the conceptual tour. For the operation-by-operation reference (every path, parameter, request body and response shape), open the API explorer — it renders the same OpenAPI 3.1 spec with Redoc, supports deep-linking to a single operation, and ships fully self-contained for air-gapped installs. The raw machine-readable spec is also served at /openapi.yaml (this docs site) and at /api/openapi.json (every OrbitalReg deployment) for code generation.
Looking for copy-paste examples in your language of choice? Jump to API code samples — every common operation in curl, Python (requests), Go (net/http), and JavaScript (fetch). For an end-to-end walkthrough that strings the calls together (sign in → mint a token → push → pull → promote), the Getting started with the API guide covers the full flow.
Authn
Three modes, in order of preference:
- OIDC token exchange (CI workloads) — exchange a CI-provided OIDC token for a short-lived bearer. See GitLab CI components.
- Service-account bearer tokens (machine-to-machine) —
orbsa_…strings minted under Project → Service accounts. - User session cookies (browser) — set by the SAML / OIDC login flow. The frontend uses
credentials: 'include'on all fetches.
curl https://orbitalreg.example.com/api/v1/projects \
-H "Authorization: Bearer orbsa_…"Resource map
| Resource | Path prefix | Notes |
|---|---|---|
| Projects | /api/v1/projects | List + CRUD; rename in place |
| Repositories | /api/v1/repos | List + CRUD; supports ?project_id=&slug= |
| Service accounts | /api/v1/projects/{id}/service_accounts | Per-project; supports ?name= |
| SA tokens | /api/v1/projects/{p}/service_accounts/{sa}/tokens | Mint endpoint returns plaintext once |
| Artifacts | /<format>/<project>/<repo>/… | Format-specific; not under /api/v1/ |
| Artifact pulls | /api/v1/security/who-pulled?… | Reverse-dep lookup |
| Retention policies | /api/v1/repos/{id}/retention/… | Plus admin mount under /api/admin/… |
| Security blocks | /api/admin/security | Admin-only |
| License policies | /api/admin/license-policies | Admin-only |
| Webhook subs | /api/admin/webhooks | Admin-only; HMAC secret is write-only |
| OIDC trust | /api/admin/oidc/trust-policies | Admin-only |
| Sigstore trust | /api/admin/sigstore/policies | Admin-only |
| Quarantine | /api/admin/quarantine | Admin-only |
| Scan findings | /api/v1/detection/findings | Filterable; used by promotion gates |
| Search | /api/v1/search | Trigram-backed global search |
| Public config | /api/public-config | Unauthenticated; help URL, version, banner |
| Health | /health/{live,ready,backup} | Unauthenticated except backup |
Pagination
List endpoints accept ?cursor=…&limit=…. The response carries next_cursor (or null). Default limit=50, max limit=500.
Errors
Every error response follows the shape:
{
"error": {
"code": "ConflictRetentionPolicyNameInUse",
"message": "A retention policy with this name already exists in the repository.",
"request_id": "0e2d…-…-…"
}
}code is stable; message is for humans and may change.
Why-blocked envelope
When a download path returns 451 (artifact blocked), the body carries:
{
"block_id": "0e2d…-…-…",
"reason": "Confirmed-malicious sample from FAS-2025-0042",
"customer_message": "…operator-supplied text…",
"blocked_until": "2026-12-31T00:00:00Z",
"public_url": "https://orbitalreg.example.com/blocked/0e2d…-…-…"
}The public_url page is unauthenticated so a developer can paste it into an incident channel.
Webhook events
A subset of the published catalog (full list at docs/integration/webhook-events.md):
artifact.uploadedartifact.promotedartifact.deletedfinding.createdfinding.threshold-exceededblock.createdblock.hitretention.deletedpolicy.changedquota.exceeded
Every event is delivered with an X-Orbitalreg-Signature header containing an HMAC-SHA256 of the payload, signed with the subscription's secret. Headers also carry a X-Orbitalreg-Event for routing and a X-Orbitalreg-Delivery UUID for dedup.
OpenAPI
curl https://orbitalreg.example.com/api/openapi.json | jq .Generate a typed client:
openapi-generator-cli generate \
-i https://orbitalreg.example.com/api/openapi.json \
-g typescript-fetch \
-o ./generatedThe generated clients are unstable across minor releases (the OpenAPI generator's templates evolve faster than our API does); regenerate on each upgrade.