API Reference
Authentication
Bearer token authentication for the Kubeadapt API: key format, minting, scope and cluster ACL semantics, rotation, and 401 vs 403 errors.
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:
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:
Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxBearer is the only supported scheme. Specifically:
- No
Authorization: Token <key>. OnlyBearer. - 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 and an optional cluster allow-list. 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*:readscopes. The key can call only the endpoints those scopes cover. See Permission Scopes for the full table. - An
allowed_cluster_idsallow-list: optional, tri-state. Documented in the next section.
These values cannot be read back from the API. To audit a key's scopes and cluster ACL, view it in the dashboard under Settings → API Keys.
The cluster ACL tri-state
The cluster allow-list has three meaningful states:
| State | Meaning in the key | Effect on requests |
|---|---|---|
nil | No 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 return 403. |
[ids] | Explicit list of cluster UUIDs. | The key can access only those clusters. Anything outside the list returns CLUSTER_ACCESS_DENIED. |
The nil and [] distinction matters: a key minted without configuring the allow-list is unrestricted (nil), while a key explicitly configured with no clusters ([]) is fully locked out. The dashboard makes the difference visible at create time.
First request
End-to-end: mint a key with organization:read, fetch the organization snapshot:
curl -H "Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
"https://public-api.kubeadapt.io/v1/organization"Expected 200 OK:
1{
2 "data": {
3 "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
4 "name": "Acme Platform",
5 "currency": "USD",
6 "counts": { "clusters_total": 14, "connected_clusters": 12 }
7 },
8 "meta": {
9 "request_id": "req_01J5K3V0Q7Y4XR8A2B3C5D7E9F",
10 "applied_at": "2026-05-21T10:30:00Z"
11 }
12}Without the Authorization header:
curl "https://public-api.kubeadapt.io/v1/organization"1{
2 "data": null,
3 "meta": {
4 "request_id": "req_01J5K3V0Q7Y4XR8A2B3C5D7E9G",
5 "applied_at": "2026-05-21T10:30:01Z"
6 },
7 "error": {
8 "code": "UNAUTHORIZED",
9 "message": "Missing or invalid Authorization header"
10 }
11}If the key is valid but lacks the scope the endpoint requires:
1{
2 "data": null,
3 "meta": {
4 "request_id": "req_01J5K3V0Q7Y4XR8A2B3C5D7E9H",
5 "applied_at": "2026-05-21T10:30:02Z"
6 },
7 "error": {
8 "code": "FORBIDDEN",
9 "message": "API key is missing the required scope",
10 "details": [{ "required": "organization:read" }]
11 }
12}If the key has the scope but the cluster is outside the allow-list:
1{
2 "data": null,
3 "meta": {
4 "request_id": "req_01J5K3V0Q7Y4XR8A2B3C5D7E9J",
5 "applied_at": "2026-05-21T10:30:03Z"
6 },
7 "error": {
8 "code": "CLUSTER_ACCESS_DENIED",
9 "message": "API key is not allowed to access this cluster",
10 "details": [{ "cluster_id": "c1a2b3c4-d5e6-7890-abcd-ef1234567890" }]
11 }
12}401 vs 403
| Code | Meaning | Cause | Resolution |
|---|---|---|---|
401 UNAUTHORIZED | The API does not recognize the key. | Missing or malformed Authorization header; key not present in active credentials; key revoked. | Fix the header. Mint or rotate the key. Retrying the same credential does not help. |
403 FORBIDDEN | The key is valid but missing a required scope. | error.details[0] carries { "required": "<scope>" }. | Mint a key with the required scope. |
403 CLUSTER_ACCESS_DENIED | The key has the scope but the requested cluster is outside its allow-list. | error.details[0] carries { "cluster_id": "<id>" }. | Add the cluster to the allow-list, or use a different key. |
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
401traffic shows up on a key you didn't expect to be in use.
Secret hygiene
- Never log the key. Redact
Authorizationin 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:readorrecommendations: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.detailscarries for each.