Sign Up

API Keys

GET
/api-keys/current

Authorization

api_key
headerAuthorizationBearer <token>

Project API key (dtn_…) as a Bearer token. Mint via the management API (POST /projects/:id/api-keys) or this deployment's key-mint CLI. Every key carries an explicit set of verb:resource project permissions chosen at mint time (PLAN-API-KEY-PERMISSIONS.md); each operation lists the project permission it requires in its security requirement, and a key lacking it is answered 403 missing required project permission: <project-permission>. Some operations require an additional permission depending on the request body, stated in the operation's description. Holding a mutating verb (write:/delete:/invoke:) implies the resource's read: permission. Operations whose api_key project-permission list is empty need no specific project permission — any live project key works (the global catalogs and the artifact-cache read).

Response Body

The presented key's metadata (never the token)

application/json
  1. response

What an API-key caller learns about the credential it presented.

created_at?|
Formatdate-time
expires_at?|

RFC 3339 expiry; null = never expires.

Formatdate-time
id*string
Formatuuid
key_prefix?|

Leading characters of the plaintext token, for recognizable display.

key_suffix?|

Trailing characters of the plaintext token; null for keys minted before the suffix was recorded.

last_used_at?|

Best-effort, flushed periodically — may lag the request that reads it.

Formatdate-time
name*string
org_id*string
Formatuuid
org_name*string
project_id*string
Formatuuid
project_name*string
project_permissions*array<string>

The key's explicit project permissions, canonical order.

service_account_id?|

The owning service account, when the key was minted for one. Only the id: service_accounts is management-plane state that workload cells do not replicate, so a name would be null there and set on home.

Formatuuid
curl -X GET 'https://example.com/api-keys/current'
{  "created_at": "2019-08-24T14:15:22Z",  "expires_at": "2019-08-24T14:15:22Z",  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "key_prefix": "string",  "key_suffix": "string",  "last_used_at": "2019-08-24T14:15:22Z",  "name": "string",  "org_id": "a40f5d1f-d889-42e9-94ea-b9b33585fc6b",  "org_name": "string",  "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",  "project_name": "string",  "project_permissions": [    "string"  ],  "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886"}
GET
/api-keys/{id}

Read one project API key's metadata (the same shape as a list item, never the token). The caller must be able to enter the key's project and hold read:project_api_keys; an unknown id, or a key in a project the caller cannot enter, is a 404 so nothing is learned about other tenants' keys. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Project API key id

Formatuuid

Response Body

Project API key metadata

application/json
  1. response
created_at?|
Formatdate-time
created_by?|

The human who minted the key — an id for a read:members holder, null for everyone else (the projects rule, #942); also null for a service-account or CLI-minted key.

Formatuuid
expires_at?|
Formatdate-time
id*string
Formatuuid
imported_from?|

"v1" when the key was created on Daytona v1 and imported by the v1 ↔ v2 key sync; null for a key created on this platform.

key_prefix?string|null
key_suffix?|

Last characters of the plaintext token, for a recognizable masked display; null for keys minted before the suffix was recorded.

last_used_at?|
Formatdate-time
mine*boolean
name*string
project_permissions*array<string>
revoked_at?|
Formatdate-time
service_account_id?|
Formatuuid
service_account_name?string|null
sync_to_v1*boolean

Whether the v1 ↔ v2 key sync copies this key to Daytona v1 (for an organization that is kept in sync with v1). true for a live key a person minted in the organization's default project unless it was opted out (PATCH /api-keys/{id}), and always for a live key imported from v1. false for every key the sync never copies: keys in other projects, service-account keys, the dashboard's own key named default, and revoked or expired keys. A v1 copy can read every sandbox, snapshot and registry of the organization on v1, which has no read permissions.

curl -X GET 'https://example.com/api-keys/497f6eca-6276-4993-bfeb-53cbbbba6f08'
{  "created_at": "2019-08-24T14:15:22Z",  "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",  "expires_at": "2019-08-24T14:15:22Z",  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "imported_from": "string",  "key_prefix": "string",  "key_suffix": "string",  "last_used_at": "2019-08-24T14:15:22Z",  "mine": true,  "name": "string",  "project_permissions": [    "string"  ],  "revoked_at": "2019-08-24T14:15:22Z",  "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886",  "service_account_name": "string",  "sync_to_v1": true}
PATCH
/api-keys/{id}

Change whether the v1 ↔ v2 key sync keeps a copy of one project API key on Daytona v1 (sync_to_v1). Turning it off deletes the v1 copy; the key keeps working on this platform. Only a live, unexpired key a person minted in the organization's default project, other than the dashboard's own key named default, is ever copied: turning it on for any other key is a 409 KEY_SYNC_NOT_APPLICABLE, and turning it off for one is a no-op. A live key imported from Daytona v1 is always synced: turning it off is a 409 IMPORTED_KEY_ALWAYS_SYNCED (delete the key to remove it from both platforms); a revoked or expired imported key is answered like any other key that is never copied. Authorized like revoking the key: the caller must be able to enter the key's project and hold write:project_api_keys for a personal key they minted, delete:project_api_keys for anyone else's, or delete:service_accounts for a service account's key. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Project API key id

Formatuuid

Request Body

application/json
  1. body
sync_to_v1*boolean

Whether the v1 ↔ v2 key sync keeps a copy of this key on Daytona v1. false deletes the v1 copy (the key keeps working here); true copies the key to v1 again. A v1 copy can read every sandbox, snapshot and registry of the organization on v1, which has no read permissions. Only a key a person minted in the organization's default project is ever copied; a key imported from v1 always is. Required: it is the only field.

Response Body

The key's metadata after the change

application/json
  1. response
created_at?|
Formatdate-time
created_by?|

The human who minted the key — an id for a read:members holder, null for everyone else (the projects rule, #942); also null for a service-account or CLI-minted key.

Formatuuid
expires_at?|
Formatdate-time
id*string
Formatuuid
imported_from?|

"v1" when the key was created on Daytona v1 and imported by the v1 ↔ v2 key sync; null for a key created on this platform.

key_prefix?string|null
key_suffix?|

Last characters of the plaintext token, for a recognizable masked display; null for keys minted before the suffix was recorded.

last_used_at?|
Formatdate-time
mine*boolean
name*string
project_permissions*array<string>
revoked_at?|
Formatdate-time
service_account_id?|
Formatuuid
service_account_name?string|null
sync_to_v1*boolean

Whether the v1 ↔ v2 key sync copies this key to Daytona v1 (for an organization that is kept in sync with v1). true for a live key a person minted in the organization's default project unless it was opted out (PATCH /api-keys/{id}), and always for a live key imported from v1. false for every key the sync never copies: keys in other projects, service-account keys, the dashboard's own key named default, and revoked or expired keys. A v1 copy can read every sandbox, snapshot and registry of the organization on v1, which has no read permissions.

curl -X PATCH 'https://example.com/api-keys/497f6eca-6276-4993-bfeb-53cbbbba6f08' \  -H 'Content-Type: application/json' \  -d '{  "sync_to_v1": true}'
{  "created_at": "2019-08-24T14:15:22Z",  "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",  "expires_at": "2019-08-24T14:15:22Z",  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "imported_from": "string",  "key_prefix": "string",  "key_suffix": "string",  "last_used_at": "2019-08-24T14:15:22Z",  "mine": true,  "name": "string",  "project_permissions": [    "string"  ],  "revoked_at": "2019-08-24T14:15:22Z",  "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886",  "service_account_name": "string",  "sync_to_v1": true}

DELETE /api-keys/{id}

DELETE
/api-keys/{id}

Revoke one project API key. The caller must be able to enter the key's project and hold delete:project_api_keys, except that revoking a personal key the caller minted (created_by = caller) is also allowed with write:project_api_keys, and revoking a key owned by a service account requires delete:service_accounts instead. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Project API key id

Formatuuid

Response Body

Revoked project API key

application/json
  1. response
revoked*string
Formatuuid
curl -X DELETE 'https://example.com/api-keys/497f6eca-6276-4993-bfeb-53cbbbba6f08'
{  "revoked": "139b8438-b6c7-4494-8941-ce249af5d379"}
DELETE
/org-api-keys/{id}

Revoke one organization API key. The caller must be a seated member holding delete:org_api_keys. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Organization API key id

Formatuuid

Response Body

Revoked organization API key

application/json
  1. response
revoked*string
Formatuuid
curl -X DELETE 'https://example.com/org-api-keys/497f6eca-6276-4993-bfeb-53cbbbba6f08'
{  "revoked": "139b8438-b6c7-4494-8941-ce249af5d379"}
GET
/orgs/{id}/api-keys

List the organization API keys of one organization. The caller must be a seated member holding read:org_api_keys. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Organization id

Formatuuid

Query Parameters

include_revoked?boolean

When true, return revoked keys as well (same semantics as the project-key list).

Response Body

Organization API keys

application/json
  1. response
org_api_keys*array<>
curl -X GET 'https://example.com/orgs/497f6eca-6276-4993-bfeb-53cbbbba6f08/api-keys'
{  "org_api_keys": [    {      "created_at": "2019-08-24T14:15:22Z",      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",      "expires_at": "2019-08-24T14:15:22Z",      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",      "key_prefix": "string",      "last_used_at": "2019-08-24T14:15:22Z",      "name": "string",      "org_permissions": [        "string"      ],      "revoked_at": "2019-08-24T14:15:22Z"    }  ]}
POST
/orgs/{id}/api-keys

Mint an organization API key (dtno_…). The caller must be a seated member holding write:org_api_keys; the requested org_permissions set must stay within the org-key mint allow-list. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Organization id

Formatuuid

Request Body

application/json
  1. body
expires_at?|

Optional expiry (D11); must be in the future. Absent = never expires.

Formatdate-time
name*string

Required — org keys have no dashboard auto-mint flow, so there is no implicit-"default" convenience (or rotation semantics) here. Option in Rust only for the specific 400; required in the contract.

org_permissions*array<string>

Required, validated against the ORG vocabulary (D4/D18/D19): explicit, at least one, project permissions are unknown values here.

Items1 <= items

Response Body

Minted organization API key; plaintext token is returned once

application/json
  1. response
expires_at?|
Formatdate-time
id*string
Formatuuid
key_prefix*string
name*string
org_id*string
Formatuuid
org_permissions*array<string>
token*string
curl -X POST 'https://example.com/orgs/497f6eca-6276-4993-bfeb-53cbbbba6f08/api-keys' \  -H 'Content-Type: application/json' \  -d '{  "name": "string",  "org_permissions": [    "string"  ]}'
{  "expires_at": "2019-08-24T14:15:22Z",  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "key_prefix": "string",  "name": "string",  "org_id": "a40f5d1f-d889-42e9-94ea-b9b33585fc6b",  "org_permissions": [    "string"  ],  "token": "string"}
GET
/projects/{id}/api-keys

List the API keys of one project. The caller must be able to enter the project and hold read:project_api_keys. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Project id, or the literal default for the caller's default project alias

Query Parameters

include_revoked?boolean

When true, return revoked keys as well. Defaults to false so the list only surfaces live keys — revoked keys are noise (and are purged after 7 days by the reaper), shown only on explicit request.

Defaultfalse

Response Body

Project API keys

application/json
  1. response
project_api_keys*array<>
curl -X GET 'https://example.com/projects/string/api-keys'
{  "project_api_keys": [    {      "created_at": "2019-08-24T14:15:22Z",      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",      "expires_at": "2019-08-24T14:15:22Z",      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",      "imported_from": "string",      "key_prefix": "string",      "key_suffix": "string",      "last_used_at": "2019-08-24T14:15:22Z",      "mine": true,      "name": "string",      "project_permissions": [        "string"      ],      "revoked_at": "2019-08-24T14:15:22Z",      "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886",      "service_account_name": "string",      "sync_to_v1": true    }  ]}
POST
/projects/{id}/api-keys

Mint a project API key. The caller must be able to enter the project and hold write:project_api_keys; the requested project_permissions set must stay within the caller's assignable project-permission ceiling. Minting for a service account additionally requires write:service_accounts, and the ceiling is intersected with that account's permissions. Only an OIDC user JWT is admitted on this route; dtno_ organization API keys are not.

Authorization

user_jwt
headerAuthorizationBearer <token>

OIDC access token of a signed-in user (the dashboard/CLI login) used on the management plane: /me, /orgs*, /projects*, /invitations*, /roles, billing, audit, API-key, and service-account routes. Every management operation documents the org/project permission the authenticated member must hold.

Path Parameters

id*string

Project id, or the literal default for the caller's default project alias

Request Body

application/json
  1. body
expires_at?|

Optional expiry (D11); must be in the future. Absent = never expires.

Formatdate-time
name?string|null
project_permissions*array<string>

Required (PLAN-API-KEY-PERMISSIONS.md D4): the key's permissions are ALWAYS explicit — no defaults, no implied full-power set, and at least one permission is required (D18); an ABSENT field or empty array is a 400. Option in Rust only so the handler can answer that specific 400; the contract marks it required so generated clients cannot omit it.

Items1 <= items
service_account_id?|

PLAN-SERVICE-ACCOUNTS.md D6: mint this key for a service account in the project's org rather than for the calling user; requires write:service_accounts (issue #926). Absent = the caller owns the key, exactly as today.

Formatuuid
sync_to_v1?|

Whether the v1 ↔ v2 key sync may copy this key to Daytona v1. Absent = true. Only a key a person mints in the organization's default project is ever copied; elsewhere the field is ignored and the response says false. A v1 copy can read every sandbox, snapshot and registry of the organization on v1, which has no read permissions; false keeps the key on this platform only. Changeable later with PATCH /api-keys/{id}.

Response Body

Minted project API key; plaintext token is returned once

application/json
  1. response
expires_at?|
Formatdate-time
id*string
Formatuuid
key_prefix*string
key_suffix*string
name*string
project_id*string
Formatuuid
project_permissions*array<string>
service_account_id?|
Formatuuid
sync_to_v1*boolean

Whether the v1 ↔ v2 key sync keeps a copy of this key on Daytona v1; same meaning as on ProjectApiKeyResponse.

token*string
curl -X POST 'https://example.com/projects/string/api-keys' \  -H 'Content-Type: application/json' \  -d '{  "project_permissions": [    "string"  ]}'
{  "expires_at": "2019-08-24T14:15:22Z",  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "key_prefix": "string",  "key_suffix": "string",  "name": "string",  "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",  "project_permissions": [    "string"  ],  "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886",  "sync_to_v1": true,  "token": "string"}