API keys
Create organization API keys and limit what each key can do with scopes.
API keys authenticate programmatic access to the SkaleData API. Each key has a scopes list that controls which endpoints it can access.
Available scopes
| Scope | Grants access to |
|---|---|
full | All endpoints (the default when you don't pass scopes) |
clusters:read | List and get clusters, clouds, node pools, pod list/logs |
clusters:write | Create, update, upgrade, destroy clusters. Manage clouds, node pools, GitHub integration, cancel jobs |
apps:read | List and get applications, health checks |
apps:deploy | Deploy images, upload DAGs, get deploy scripts, registry tokens, dev credentials |
apps:manage | Create, update, delete, restart applications |
jobs:read | List and get jobs |
terminal:exec | Terminal pod setup |
How scopes work
- A key with the
fullscope bypasses all scope checks -- it can call any endpoint that accepts API key auth. - Non-
fullkeys must have the specific scope required by each endpoint. If the scope is missing, the API returns 403 Forbidden with the messageAPI key missing required scope: <scope>. - Some endpoints are user-only and reject API key auth entirely (billing management, API key management, data plane tokens).
- To call a deployed app through its SkaleData URL (for example, Airflow's REST API), a key needs the
fullscope. A narrower key gets 403 there, because those requests run as the app's admin identity.
Creating scoped keys
When creating an API key via POST /api-keys, pass a scopes array:
curl -X POST https://api.skaledata.com/api-keys \
-H "Authorization: Bearer <clerk-jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "ci-deploy",
"scopes": ["apps:deploy", "clusters:read"]
}'The returned key can deploy images and read cluster info, but cannot create or destroy clusters. The response's scopes field shows the scopes the key was created with. Scopes must be known, listed once each, and full can't be combined with other scopes; otherwise the API returns 422.
Earlier, POST /api-keys ignored the scopes field and created every key with full. If you created keys with scopes before this was fixed, they have full access. To check, call GET /api-keys and look at each key's scopes; replace any key that's broader than you need.
Scope combinations
Common patterns for CI/CD and automation:
| Use case | Scopes |
|---|---|
| Full access (default) | ["full"] |
| CI/CD deploy pipeline | ["apps:deploy", "clusters:read"] |
| Monitoring / dashboards | ["clusters:read", "apps:read", "jobs:read"] |
| Cluster management automation | ["clusters:read", "clusters:write"] |
| DAG sync bot | ["apps:deploy"] |
Endpoints that reject API keys
These endpoints require a user session (Clerk JWT) and will return 403 if called with an API key:
POST/DELETE /api-keys/*-- API key managementPOST /billing/*-- billing managementPOST /clusters/{id}/data-plane-token-- data plane handoff (needs user email)POST /applications/{id}/app-token-- app-scoped token for calling app APIs (needs user email)
To call a deployed app's own REST API (Airflow, Airbyte, …) with a long-lived key instead of a browser session, an API key works directly against the data plane — see App APIs.