Skip to content

API overview

https://cavsnode.com/api/v1

Health checks sit outside the version prefix:

Endpoint Auth Purpose
GET /readyz none Readiness, including a database ping. Use this for external checks.
GET /healthz none Liveness. Internal only — externally the load balancer answers this path itself.
GET /api/v1/plans none The public plan catalogue
Terminal window
curl -sS https://cavsnode.com/readyz # → ready
curl -sS https://cavsnode.com/api/v1/plans # → { "plans": [...] }

Everything is under /api/v1. Additive changes (new fields, new endpoints) ship without a version bump, so clients must tolerate unknown response fields.

The server may reply with X-CAVS-Deprecation: <message>. Surface it as a warning, never as an error.

Authorization: Bearer <credential>

Two credential families on the same header:

Credential Shape Who
Firebase ID token a JWT the dashboard
CAVS API token cavs_pat_…, cavs_repo_…, cavs_ci_… everything else

See Authentication and API tokens.

Parameter Accepts
{orgID} organization UUID or slug
{repoID} repository UUID only
{oid} 64-character lowercase hex SHA-256
{sha} a Git commit SHA
{tag} a Git tag name
Rule Detail
Content type application/json on any request with a body
Body limit 1 MiB for control-plane requests
Unknown fields rejected with 400, not ignored
Timeout 60 seconds per request, server-side

That unknown-field strictness is deliberate: a typo’d field name fails loudly instead of being silently dropped.

Success bodies wrap their payload in a named key:

{ "repositories": [ ] }
{ "session": { }, "generation": 42 }
{ "webhook": { } }

Errors always use the same envelope:

{
"error": {
"code": "quota_exceeded",
"message": "storage quota exceeded for plan developer",
"request_id": "8c1f2e4a-…",
"details": { "reason": "storage", "limit": 107374182400, "used": 106300000000 }
}
}

See Errors for the full taxonomy.

Every response carries a locked-down header set — Content-Security-Policy: default-src 'none', X-Frame-Options: DENY, Referrer-Policy: no-referrer, Cache-Control: no-store, and HSTS over TLS. Details in Security model.

Idempotency-Key: <stable string>

Honoured on: creating an upload session, finalizing an upload, creating a snapshot. Resending the same key returns the same resource instead of duplicating work.

Pick a key derived from what makes the operation unique — a build id, a content hash, a period — not a random value:

Terminal window
-H "Idempotency-Key: upload-$OID"
-H "Idempotency-Key: build-$CI_PIPELINE_ID"
-H "Idempotency-Key: monthly-$(date -u +%Y-%m)"
Sustained 30 requests/second
Burst 60
Keyed by token id → user id → client IP

Exceeding it returns 429 with code: "rate_limited".

Presigned URLs are not rate-limited by CAVS: bulk transfers run against object storage, so throughput doesn’t consume your API budget.

Two styles, depending on the endpoint.

Offset — most list endpoints:

?limit=50&skip=0
Default Max
limit 50 200 (100 or 50 on some endpoints)
skip 0 10000

Cursor — time-ordered lists. Pass the last item’s timestamp back as before (RFC 3339):

?limit=50&before=2026-07-01T00:00:00Z

The organization artifact registry returns next_before for you to feed back.

Every response carries:

X-Correlation-Id: 8c1f2e4a-…
X-Request-Id: 8c1f2e4a-…

Both are the same value, and error bodies embed it as request_id. Send your own X-Correlation-Id to thread a client-side trace through the platform. Quote it in support requests — it’s how a specific failure gets found in the logs.

User-Agent: cavs-<lang>/<version>
X-CAVS-Client: python-sdk | javascript-sdk | cli | generic-http
X-CAVS-Integration: cli | python-sdk | github-actions | gitlab-ci | generic-http | …
X-CAVS-Integration-Version: <version>
X-CAVS-Run-ID: <optional>

Set them in your own clients.

Only the configured dashboard origins are allowed, with an explicit allowlist: methods GET POST PUT PATCH DELETE OPTIONS, headers Authorization, Content-Type, Idempotency-Key, Accept. Credentials are allowed; preflight is cached for 300 seconds.

Group Reference
Identity, search, notifications, invitations Identity & discovery
Organizations, members, tokens, webhooks, storage, billing Organizations · Tokens, webhooks & billing
Repositories, files, commits, releases, graph, analytics Repositories
Upload sessions Uploads
Download authorization Downloads
Git LFS batch and the CAVS chunk tree Git LFS endpoints
Git index ingest Git index ingest
Everything, in one table Endpoint index

Documented in the SDK contract but not deployed — these return 404:

  • GET /resolve?uri=cavs://…
  • GET /artifacts/{id} and /artifacts/{id}/versions (the repository-scoped GET /repositories/{repoID}/artifacts/{oid} does exist)
  • POST /repositories/{repoID}/lfs/verify
  • The Runs API (/runs)
  • Service accounts (/organizations/{org}/service-accounts) and cavs_sk_ keys

There is no published OpenAPI document yet.