API overview
Describes the authentication, the conventions, and the error format of the API.
Last updated
Base URL and bodies
https://dev.kloudlite.io/v1. Bodies are JSON in both directions unless a route says otherwise. Route pages write the full path, for example POST /v1/workspaces.
Authentication
Send Authorization: Bearer <token> on every request. A missing, invalid, expired, or revoked token is 401 missing or invalid token. The token decides which routes accept it.
| Token | Held by | Lives | Accepted on |
|---|---|---|---|
| Session | the console, after sign-in | 12 hours | every route of this API |
| CLI login | kode login; you can pass it as $KODE_TOKEN | 30 days; revocable (/v1/cli/tokens), so a revoked one stops working at once | the workspace, environment, desk, capsule, pipeline, secret, quota, request, and region routes, and the credential routes (/v1/tokens, /v1/keys, /v1/cli/tokens). The team routes take a desk only |
| API token | POST /v1/tokens, as $KODE_TOKEN | 1 to 365 days (default 90); revocable at once | the workspace, environment, desk, capsule, pipeline, pipeline run, volume, and snapshot routes, and quota and regions, within the reach and grants of the token. Each route needs a verb that a grant holds. Not the routes for tokens, keys, teams, secrets, or connectors |
| Desk tool | the desk, in a file that the platform renews | 15 minutes; refused unless its desk is running | the routes the desk's tools call: quota, requests (open, list, read), regions, the workspace verbs (list, create, restore, get, patch, delete, tools, packages/update, trees, clone, push, start, stop), the environment verbs (including intercepts), desks/{id}/hold, desks/{id}/environment, builders/me, and the volumes routes |
| Workspace tool | kd inside a workspace | 24 hours, re-minted every five minutes | seven routes: GET and PATCH /v1/workspaces/{id}, POST /v1/workspaces/{id}/packages/update, GET /v1/environments, GET /v1/workspaces/registries, POST /v1/workspaces/registry-credential, POST /v1/git/credential |
| Pipeline run | a pipeline run, minted by the platform | up to 25 hours | the capsule routes (POST /v1/capsules, GET /v1/capsules/{id}, terminate, logs, attach, wait), GET, clone, start, and DELETE on /v1/environments/{id}, and POST /v1/desks, DELETE /v1/desks/{id} |
| Git credential | a pipeline job with permissions.git: read, or a capsule that you made, as $KD_GIT_TOKEN | minted with the other tokens of the job, or when the capsule is made; answered only while the job or the capsule runs | POST /v1/git/credential only |
A restricted token (desk tool, workspace tool, pipeline run, git credential) on any other route is the same 401 as a bad token. An API token outside its reach or grants is the same 401. SSH and signing keys under /v1/keys do not authenticate this API.
A token needs a username. Without one, the workspace, environment, and volume routes answer 403 pick a username before using workspaces. This API has no admin route.
Who owns what
What you create belongs to your username. To create under a team, be a member and name it in the body (team on a workspace, owner on an environment).
- A team member whose access is paused gets
403 your access to {team} is paused. - A removed member gets
403 you are no longer a member of {team}. - Something that you cannot act on is
404 not found, the same as something that does not exist.
Ids, names, and team/name
Every object has an id: a prefix, a dash, and 16 lowercase hex digits, such as ws-0123456789abcdef, env-…, cap-…. A route that takes {id} for a workspace or an environment also accepts the name you gave it.
- A name is searched among your own objects first, then your teams'. A workspace named
backendthat you own beats a team'sbackend. - To name one exactly, qualify it:
team/namefor a workspace (/namefor your personal one),owner/namefor an environment. A slash does not fit in a path segment, so the same thing is the query?owner=teamon the plain route. - A name that still matches more than one object is
409with a JSON body that lists them:{"error": "\"backend\" is ambiguous; qualify it as owner/name", "matches": [{"id": "ws-…", "name": "backend", "team": "acme"}]}. - Desks follow the workspace rule (id, name, or
team/name). Capsules are addressed by their id only, and/v1/volumes/{name}by the volume's name.
Errors
The status comes first; the body is one sentence. Most handlers answer in plain text. The workspace lifecycle verbs, capsules, and desks answer {"error": "…"}. Errors says which is which. Show the body in either form.
| Status | Means |
|---|---|
400 | The request is malformed |
401 | No token, a bad, expired, or revoked one, a restricted token on a route it may not call, or a desk tool token whose desk is not running |
403 | The token is real but not allowed: no username yet, paused, or removed from the team, or not a member |
404 | Not found, or not yours to see |
429 | An API token has its limit of runs in flight: this token has {n} runs in flight; the limit is {max} |
409 | A state conflict (the object is in the wrong state, a name is taken, the name is ambiguous), or over quota |
422 | A body that parses but cannot be used: a package pin that cannot be resolved or is not cached, an unknown region, a TTL out of range |
5xx | The server or the cluster failed: retry |
A 409 over quota names the dimension and the numbers: {dimension}: {used} of {limit} in use; request more under Quota.
Lists
List routes return the whole set you can see in one response. None takes a page size or a cursor.