API Keys
Generate scoped Bearer tokens for headless access — scripts, CI pipelines, and AI agents.
API keys are long-lived Bearer tokens for programmatic access to the Spunto API — for scripts, CI pipelines, or AI agents that need to operate the platform without a browser session. They're scoped to a single organization and to a specific set of permissions, and can be revoked independently of any user's login session.
Open Account Settings
From the dashboard, go to Account Settings and find the API keys card.
Pick an organization
A key is always scoped to one organization. If you belong to several, pick the one the key should act on.
Choose owner type
Personal keys act as you — they stop working if you lose membership in the org. Org (service account) keys belong to the organization itself and keep working even if the creator leaves; creating one requires the admin or owner role.
Select scopes
Pick the narrowest set of scopes the script or agent actually needs (see Scopes below).
Copy the token
The full token (spk_...) is shown exactly once, right after creation. Store it somewhere safe — Spunto only ever stores a hash of it, so it can't be shown again. If you lose it, revoke the key and create a new one.
Personal (ownerType: "user") | Org service account (ownerType: "org") | |
|---|---|---|
| Acts as | You | The organization |
| Who can create it | Any org member, for themselves | admin / owner only |
| Survives creator leaving the org | No — tied to your membership | Yes |
| Typical use | Personal scripts, your own CLI tooling | Long-running CI, an autonomous agent deployed in prod |
Scopes are coarse and resource-based, in the form resource:action. A request needs at least one matching scope (or the * wildcard) to pass — sessions created via the dashboard login (JWT/cookie) are unaffected and always have full access; scoping only applies to API keys.
| Scope | Grants |
|---|---|
* | Every scope below — full access |
projects:read | List/get projects, image builds, version history |
projects:write | Create/update/delete projects, trigger builds, restore versions |
workers:read | List/get workers, logs, stats, git status, ports |
workers:write | Spawn/stop/start/rebuild/delete workers |
workers:exec | Terminal sessions and SSH tokens — interactive shell access inside a worker |
deployments:read | List/get deployments and services, service logs, job runs |
deployments:write | Create/update/delete deployments and services, start/stop/deploy, run jobs |
nodes:read | List/get worker nodes, inventory |
nodes:write | Create/delete nodes, rotate tokens, drain — infrastructure-level access |
A request is matched against GET → :read, every other HTTP method → :write, except terminal/SSH-token endpoints under /workers/..., which always require :exec regardless of method.
Send it as a standard Bearer token — exactly like a session JWT:
curl -H "Authorization: Bearer spk_..." \
https://spunto.net/api/orgs/{orgId}/projectscurl -X POST \
-H "Authorization: Bearer spk_..." \
-H "Content-Type: application/json" \
-d '{ "name": "ci-worker", "image": "..." }' \
https://spunto.net/api/orgs/{orgId}/projects/{projectId}/workersA request with a missing, malformed, revoked, or expired key returns 401 Unauthorized. A request with a valid key but a missing scope returns 403 Forbidden.
GET /api/orgs/:orgId/api-keys List keys (token values are never returned, only a `tokenPrefix`)
POST /api/orgs/:orgId/api-keys Create a key — { name, ownerType, scopes } → { ...key, token }
DELETE /api/orgs/:orgId/api-keys/:keyId Revoke a keyThe full request/response schemas (including the ApiKey/ApiKeyCreated shapes) are in the interactive reference — look for the ApiKeys tag at /api/docs, or browse the raw spec at /openapi.json.
curl -X DELETE \
-H "Authorization: Bearer <session token, not an API key>" \
https://spunto.net/api/orgs/{orgId}/api-keys/{keyId}Revocation is immediate — the very next request made with that token returns 401. The key row isn't deleted, only marked revoked, so it stays visible (and auditable) in the list.
- No expiration support yet. Keys are valid until revoked — there's no "expires in 90 days" option in the dashboard or API today.
- No per-project/per-deployment restriction. A scope like
workers:writeapplies to every project in the org, not a single one. - No rate limiting. A misbehaving script or agent loop using an API key is bound by the same limits as everything else — i.e. none yet.
