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:
| Resource | Path |
|---|---|
| Curated OpenAPI JSON | GET /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
}
erroris a stable machine code: branch on this, not onmessage.messageis human-readable and may change; internal exception text never crosses the wire.correlation_idaccompanies server-side (5xx) failures: quote it in a support request.detailsandretryableappear when meaningful.
The stable codes and their HTTP statuses:
error | HTTP | Meaning |
|---|---|---|
invalid_request | 400 | The request was malformed or failed validation. |
unauthorized | 401 | No valid credential was presented. |
forbidden | 403 | The credential is valid but lacks the permission. |
not_found | 404 | No such resource (also returned instead of revealing a forbidden resource). |
conflict | 409 | The request conflicts with current state. |
rate_limited | 429 | Too many requests: see rate limiting below. |
service_unavailable | 503 | A dependency is temporarily unavailable. |
internal_error | 500 | An 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:
| Header | On |
|---|---|
X-RateLimit-Limit | every response |
X-RateLimit-Remaining | every response |
X-RateLimit-Reset | every response |
Retry-After | the 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
| Gate | Pass | Refuse |
|---|---|---|
| Rate budget | continue | 429 rate_limited + Retry-After |
| Authentication | continue | 401 unauthorized |
| Authorization | 200 + resource | 403 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>"
Related topics
- Programmatic authentication, obtain an API key or OAuth token.
- Public API reference, the served OpenAPI document and status legend.
- Jobs API, a worked surface that follows every convention here.