Skip to main content

API conventions & first call

Every operation in the public API shares the same base path, error envelope, rate-limiting behavior, and pagination. Learn them once and they hold across data credentials, the Jobs API, and the rest of the surface.

Base path and discovery​

The public API is versioned under /api/public/v1. The node does not serve the full internal spec; it serves a curated, deny-by-default document:

ResourcePath
Curated OpenAPI JSONGET /api/public/v1/openapi.json
Interactive browser (Swagger UI)GET /api/public/v1/docs
Administrative surface/api/public/v1/admin/…

The OpenAPI document is the source of truth for which operations exist and each one's x-status (Live or Partial). See Public API reference for how the curation works.

Your first call​

You authenticate with either a scoped API key or an OAuth 2.1 access token. See Programmatic authentication for how to obtain each. Both are presented the same way, as a bearer token.

With an API key:

curl -sS https://<node>/api/public/v1/openapi.json \
-H "Authorization: Bearer s9k_live_…"

With OAuth (client-credentials exchange, then the call):

# 1. Exchange client credentials for a short-lived access token
TOKEN=$(curl -sS -X POST https://<node>/oauth/token \
-d grant_type=client_credentials \
-u "<client_id>:<client_secret>" | jq -r .access_token)

# 2. Call the API with the access token
curl -sS https://<node>/api/public/v1/openapi.json \
-H "Authorization: Bearer $TOKEN"

A successful call returns the resource; a refused one returns the error envelope below.

The error model​

Every error (from a handler or from the gateway itself) returns one envelope:

{
"error": "invalid_request",
"message": "human-readable summary",
"correlation_id": "…",
"details": {},
"retryable": false
}
  • error is a stable machine code: branch on this, not on message.
  • message is human-readable and may change; internal exception text never crosses the wire.
  • correlation_id accompanies server-side (5xx) failures: quote it in a support request.
  • details and retryable appear when meaningful.

The stable codes and their HTTP statuses:

errorHTTPMeaning
invalid_request400The request was malformed or failed validation.
unauthorized401No valid credential was presented.
forbidden403The credential is valid but lacks the permission.
not_found404No such resource (also returned instead of revealing a forbidden resource).
conflict409The request conflicts with current state.
rate_limited429Too many requests: see rate limiting below.
service_unavailable503A dependency is temporarily unavailable.
internal_error500An unexpected server-side failure.

Rate limiting​

Two independent controls can throttle a call.

Gateway (per-client) limit. The front door runs a per-client-IP token bucket. Every response carries the current budget, and a throttled request is refused with a 429 and the rate_limited envelope:

HeaderOn
X-RateLimit-Limitevery response
X-RateLimit-Remainingevery response
X-RateLimit-Resetevery response
Retry-Afterthe 429 response

A 429 is retryable: true; honor Retry-After before retrying, ideally with backoff.

Per-endpoint limit. A published notebook/compute endpoint can carry its own rate_limit_rpm (requests per minute, default 60), configured when the endpoint is registered. Exceeding it refuses the call at that endpoint. This is separate from the gateway budget above.

Figure: a request passes the rate budget, then authentication and authorization; each gate refuses with the shared error envelope. Every response carries the X-RateLimit-* headers.

Table equivalent

GatePassRefuse
Rate budgetcontinue429 rate_limited + Retry-After
Authenticationcontinue401 unauthorized
Authorization200 + resource403 forbidden (or 404 not_found)

Pagination​

List endpoints use limit and offset query parameters (offset-based; there is no cursor). Defaults and ceilings vary by endpoint, for example, Jobs run listing defaults to limit=200 (max 2000). Each family returns its own list shape; there is no single wrapper envelope across the API, so read the operation in the OpenAPI document for its exact response.

curl -sS "https://<node>/api/public/v1/admin/jobs/runs?limit=50&offset=100" \
-H "Authorization: Bearer <token>"