Skip to content

API Reference

Authentication

Bearer token authentication for the Kubeadapt API: key format, minting, scope and cluster ACL semantics, rotation, and 401 vs 403 errors.

Last updated


Every authenticated /v1 request carries a Bearer API key in the Authorization header. Keys are minted in the Kubeadapt dashboard, encode a tenant identity plus a scope set, and optionally restrict access to a subset of clusters.

API key format

Every Kubeadapt API key has the shape:

plaintext
ka_live_<32 base62 characters>

The ka_live_ prefix identifies it as a production key. The 32 characters after are base62 (the alphanumeric alphabet [A-Za-z0-9]). There are no other formats: no ka_test_, no JWT-style three-segment tokens, no UUID-shaped keys.

Send the key as a Bearer credential on every authenticated request:

plaintext
Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Bearer is the only supported scheme. Specifically:

  • No Authorization: Token <key>. Only Bearer.
  • No query-parameter keys. ?api_key=... is not honored. Putting secrets in URLs lets them leak into proxy logs and browser history.
  • No cookies. The API is stateless. There is no session, no CSRF token, no login endpoint.
  • No basic auth. No username/password.

Every /v1/* endpoint except the OpenAPI spec endpoints (/v1/openapi.json, /v1/openapi.yaml, /v1/docs) requires the header. Sending a request without it returns 401 UNAUTHORIZED.

Minting a key

Keys are created from app.kubeadapt.io under Settings → API Keys with a chosen scope set. Keys created in the dashboard cover every cluster in the tenant (allow-list nil). A per-cluster allow-list can currently only be set by support. The full key is shown once at creation; Kubeadapt does not store it in retrievable form, so a lost key cannot be recovered — only revoked and replaced. For the step-by-step flow including scope-selection guidance, see Mint an API key.

What a key carries

A key is opaque to the client. From your side, it's 40 characters of text. Every key carries three pieces of authorization data:

  • tenant_id: the organization the key belongs to. Every request is automatically scoped to this tenant. There is no cross-tenant API path, no way to fetch another organization's data with your key.
  • A scope set: one or more of the nine *:read scopes. The key can call only the endpoints those scopes cover. See Permission Scopes for the full table.
  • An allowed_cluster_ids allow-list: optional, tri-state. Documented in the next section.

These values cannot be read back from the API. A key's scopes are listed in the dashboard under Settings → API Keys. To confirm a key's cluster allow-list, ask support.

The cluster ACL tri-state

The cluster allow-list has three meaningful states:

StateMeaning in the keyEffect on requests
nilNo allow-list configured (the default).The key can access every cluster in the tenant. Future clusters auto-included.
[]Explicit empty allow-list.The key cannot access any cluster. List endpoints return empty; per-cluster paths and Cost Explorer queries return 403.
[ids]Explicit list of cluster UUIDs.The key can access only those clusters. Anything outside the list returns CLUSTER_ACCESS_DENIED, including a Cost Explorer query whose cluster_ids are all outside the list.

The nil and [] distinction matters: a key minted without an allow-list is unrestricted (nil), while a key explicitly configured with no clusters ([]) is fully locked out. Keys created in the dashboard are always nil.

First request

End-to-end: mint a key with organization:read, fetch the organization snapshot:

bash
curl -H "Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  "https://public-api.kubeadapt.io/v1/organization"

Expected 200 OK:

json
1{
2  "data": {
3    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
4    "kind": "Organization",
5    "metadata": { "name": "Acme Platform", "domain": "acme.io", "plan_type": "enterprise", "is_active": true, "created_at": "2026-01-03T00:08:51Z" },
6    "utilization": { "counts": { "clusters": 14, "connected_clusters": 12 } },
7    "cost": { "current_run_rate_hourly": { "amount": "233.0945", "currency": "USD" }, "last_updated_at": "2026-05-21T10:29:00Z" }
8  },
9  "meta": {
10    "request_id": "0196f1c2-3550-76c7-9f9a-408a74373fee",
11    "applied_at": "2026-05-21T10:30:00Z"
12  }
13}

See Organization for the complete Organization schema.

Without the Authorization header:

bash
curl "https://public-api.kubeadapt.io/v1/organization"
json
1{
2  "data": null,
3  "meta": {
4    "request_id": "0196f1c2-d0b2-7db6-a774-46df52615dac",
5    "applied_at": "2026-05-21T10:30:01Z"
6  },
7  "error": {
8    "code": "UNAUTHORIZED",
9    "message": "missing authorization header",
10    "details": [{ "reason": "missing_header" }]
11  }
12}

If the key is valid but lacks the scope the endpoint requires:

json
1{
2  "data": null,
3  "meta": {
4    "request_id": "0196f1c2-9745-77e4-8b21-ac030e69dc0c",
5    "applied_at": "2026-05-21T10:30:02Z"
6  },
7  "error": {
8    "code": "FORBIDDEN",
9    "message": "insufficient scope",
10    "details": [{ "required": ["organization:read"], "granted": ["clusters:read"] }]
11  }
12}

If the key has the scope but the cluster is outside the allow-list:

json
1{
2  "data": null,
3  "meta": {
4    "request_id": "0196f1c2-9b4f-79f1-97ad-51c226af6447",
5    "applied_at": "2026-05-21T10:30:03Z"
6  },
7  "error": {
8    "code": "CLUSTER_ACCESS_DENIED",
9    "message": "access to this cluster is not allowed"
10  }
11}

401 vs 403

CodeMeaningCauseResolution
401 UNAUTHORIZEDThe API could not verify the key.Missing or malformed Authorization header; key unknown, revoked or expired; or, rarely, a temporary failure while verifying the key.Fix the header. If a key that worked minutes ago starts failing, retry with backoff before you rotate it.
403 FORBIDDENThe key is valid but missing a required scope.error.details[0] carries { "required": ["<scope>"], "granted": ["<scope>", …] }.Mint a key with the required scope.
403 CLUSTER_ACCESS_DENIEDThe key has the scope but the requested cluster is outside its allow-list.No details; the cluster is the one in your request.Use a key whose allow-list covers the cluster.

See Error Handling for the full code catalog and retry policy.

Rotation

Kubeadapt manages key infrastructure rotation transparently — no client action is required, and existing keys remain valid. Client-side rotation (minting a new key, cutting over, revoking the old one) is the integration's responsibility; both keys remain valid until the old one is revoked. For the cutover procedure, see Rotate an API key.

Revocation

Revoke a key from Settings → API Keys → Revoke. The revocation takes effect on the next request and is immediate — there is no grace window. A revoked key returns 401 UNAUTHORIZED.

Revoke a key when:

  • The integration that owned it is decommissioned.
  • The key is exposed in logs, source control, screenshots, or any communication channel you don't fully control.
  • The person who created it leaves the team and you don't have another owner.
  • Any unexplained 401 traffic shows up on a key you didn't expect to be in use.

Secret hygiene

  • Never log the key. Redact Authorization in application logs before they leave the host. If HTTP middleware logs headers by default, configure an allow-list.
  • Never embed it client-side. No browser JavaScript, mobile app binary, or desktop app binary. Browser-side use must proxy through a server you control so the key stays server-side.
  • Never store it in chat tools or shared documents. Chat history, email threads, Confluence, Notion, and Google Docs are all searchable and backed up. Use a secrets manager.
  • Use one key per integration. Shared keys cannot be revoked without breaking every consumer.
  • Use the minimum scopes the integration needs. A chargeback key does not need nodes:read or recommendations:read. See Permission Scopes for the per-endpoint scope table and example minimum-token recipes.

Keys cannot be partially revoked or scope-narrowed after the fact. The only response to a leaked key is to revoke it and mint a replacement.

See also

  • API Overview: base URL, envelope shape, rate limits, the full endpoint index.
  • Permission Scopes: the nine read scopes, the endpoints each covers, and example minimum-token recipes for common integrations.
  • Error Handling: the full error code catalog and what error.details carries for each.