desk-ops
https://api.gaiadesk.net/v1 /desks/{id}/tokens Scope tokensThe desk's agent tokens (never their secrets).
Token administration is the desk OWNER's: a signed-in person's own account on their own desk. An agent token is refused whatever its scopes (403 agent_cannot_admin).
Parameters
idstringpathrequiredGaiaDesk-E2EstringheaderApiE2eRequest, as base64url of its JSON) in place of a plaintext body or parameters. The answer is then sealed too (ApiE2eAnswer, ApiE2eStreamEvent, ApiE2eFrame). A POST may instead send the body {"e2e": …} (ApiE2eBody). See the "End-to-end encryption" section of docs/api/README.md.wake_sintegerqueryCode samples
cURL
curl -X GET "https://api.gaiadesk.net/v1/desks/{id}/tokens" \
-H "Authorization: Bearer $GAIADESK_API_KEY" \
-H "GaiaDesk-E2E: <value>"TypeScript
Python
Go
PHP
Ruby
Java
Responses
Example
{
"tokens": [
{
"cwd": "string",
"expires_at_ms": 0,
"id": "string",
"issued_at_ms": 0,
"label": "string",
"last_used_ms": 0,
"low_priv": true,
"revoked": false,
"scopes": []
}
]
}TokenList
tokensTokenInfo[]requiredShow child parameters
cwdstringNone: not confined.expires_at_msintegerrequiredidstringrequiredissued_at_msintegerrequiredlabelstringrequiredlast_used_msintegerlow_privbooleanrevokedbooleanscopesstring[]screen, exec, shell, cp, forward, jobs, admin (ask to run as administrator — never implied). Empty for a token from before scopes, which is a screen (Agent Access) token.{
"tokens": [
{
"cwd": "string",
"expires_at_ms": 0,
"id": "string",
"issued_at_ms": 0,
"label": "string",
"last_used_ms": 0,
"low_priv": true,
"revoked": false,
"scopes": []
}
]
}ApiE2eAnswer
e2eobjectrequiredShow child parameters
vintegerrequiredeventsApiE2eFrame[]requiredShow child parameters
seqintegerrequirednoncestringrequiredciphertextstringrequired{
"e2e": {
"v": 0,
"events": [
{
"seq": 0,
"nonce": "string",
"ciphertext": "string"
}
]
}
}X-Request-Idstringreq_…), also in every error body. Quote it to support.RateLimit-LimitintegerRateLimit-RemainingintegerRateLimit-Resetintegerusage).Example
{
"error": {
"desk": "string",
"kind": "string",
"message": "string",
"reason": "string",
"request_id": "string",
"status": 0
},
"e2e": {
"v": 0,
"events": [
{
"seq": 0,
"nonce": "string",
"ciphertext": "string"
}
]
}
}Schema
errorError & objectrequiredShow child parameters
deskstringkindstringrequiredmessagestringrequiredreasonstringoffline, unknown_desk, not_online, network, not_signed_in, timeout, local, …request_idstringrequiredstatusintegerGaiaDesk-Held) — the HTTP status this failure would have had, had its 200 not been sent already.e2eobjectmessage here is a placeholder).Show child parameters
vintegerrequiredeventsApiE2eFrame[]requiredShow child parameters
seqintegerrequirednoncestringrequiredciphertextstringrequiredrefused, unauthenticated).Same as 400 · GET /desks/{id}/tokens
refused).Same as 400 · GET /desks/{id}/tokens
unreachable, unknown_desk).Same as 400 · GET /desks/{id}/tokens
unreachable, with the reach log's reason: silent, closed, …) or could not be woken within wake_s; or it runs a GaiaDesk from before desk operations (protocol, desk_too_old: update GaiaDesk on this desk).Same as 400 · GET /desks/{id}/tokens
rate_limited), or the desk already runs 16 API operations (desk_busy).Same as 400 · GET /desks/{id}/tokens
Retry-Afterintegerconnection_lost), or answered something this server cannot read (protocol).Same as 400 · GET /desks/{id}/tokens
unreachable, desk_ops_disabled).Same as 400 · GET /desks/{id}/tokens
https://api.gaiadesk.net/v1 /desks/{id}/tokens Scope tokensMint a scoped agent token on the desk (the secret is returned once).
Token administration is the desk OWNER's: a signed-in person's own account on their own desk. An agent token is refused whatever its scopes (403 agent_cannot_admin).
The admin scope cannot be minted through the API (403 refused, error.reason admin_not_via_api): its secret would cross the API. Mint it with gaiadesk-cli token create --scope exec,admin (docs/admin-access.md).
Parameters
idstringpathrequiredGaiaDesk-E2EstringheaderApiE2eRequest, as base64url of its JSON) in place of a plaintext body or parameters. The answer is then sealed too (ApiE2eAnswer, ApiE2eStreamEvent, ApiE2eFrame). A POST may instead send the body {"e2e": …} (ApiE2eBody). See the "End-to-end encryption" section of docs/api/README.md.Idempotency-KeystringheaderIdempotent-Replayed: true); the same key with a different request is refused (usage, idempotency_key_reused).wake_sintegerqueryRequest body
application/json
Example
{
"cwd": "string",
"expires_secs": 0,
"low_priv": false,
"name": "string",
"scopes": {}
}ApiMintSpec
cwdstringexpires_secsintegerrequiredlow_privbooleannamestringrequiredscopesrequired{
"cwd": "string",
"expires_secs": 0,
"low_priv": false,
"name": "string",
"scopes": {}
}ApiE2eBody
e2eobjectrequirede2e_pub): X25519 with the caller's ephemeral key pub, HKDF-SHA256, XChaCha20-Poly1305 (protocol/src/e2e.rs; docs/api/README.md). Base64url, no padding.Show child parameters
vintegerpubstringrequirednoncestringrequiredciphertextstringrequired{
"e2e": {
"v": 0,
"pub": "string",
"nonce": "string",
"ciphertext": "string"
}
}Code samples
cURL
curl -X POST "https://api.gaiadesk.net/v1/desks/{id}/tokens" \
-H "Authorization: Bearer $GAIADESK_API_KEY" \
-H "GaiaDesk-E2E: <value>" \
-H "Idempotency-Key: <value>" \
-H "Content-Type: application/json" \
-d '{"cwd":"string","expires_secs":0,"low_priv":false,"name":"string","scopes":{}}'TypeScript
Python
Go
PHP
Ruby
Java
Responses
Example
{
"tokens": [
{
"desk": "string",
"secret": "string",
"token": {
"cwd": "string",
"expires_at_ms": 0,
"id": "string",
"issued_at_ms": 0,
"label": "string",
"last_used_ms": 0,
"low_priv": true,
"revoked": false,
"scopes": []
}
}
]
}MintResult
tokensMintedToken[]requiredShow child parameters
deskstringrequiredsecretstringrequiredtokenobjectrequiredShow child parameters
cwdstringNone: not confined.expires_at_msintegerrequiredidstringrequiredissued_at_msintegerrequiredlabelstringrequiredlast_used_msintegerlow_privbooleanrevokedbooleanscopesstring[]screen, exec, shell, cp, forward, jobs, admin (ask to run as administrator — never implied). Empty for a token from before scopes, which is a screen (Agent Access) token.{
"tokens": [
{
"desk": "string",
"secret": "string",
"token": {
"cwd": "string",
"expires_at_ms": 0,
"id": "string",
"issued_at_ms": 0,
"label": "string",
"last_used_ms": 0,
"low_priv": true,
"revoked": false,
"scopes": []
}
}
]
}ApiE2eAnswer
e2eobjectrequiredShow child parameters
vintegerrequiredeventsApiE2eFrame[]requiredShow child parameters
seqintegerrequirednoncestringrequiredciphertextstringrequired{
"e2e": {
"v": 0,
"events": [
{
"seq": 0,
"nonce": "string",
"ciphertext": "string"
}
]
}
}X-Request-Idstringreq_…), also in every error body. Quote it to support.RateLimit-LimitintegerRateLimit-RemainingintegerRateLimit-ResetintegerIdempotent-Replayedstringtrue when this answer is a stored one, replayed for a repeated Idempotency-Key.refused, unauthenticated).Same as 400 · GET /desks/{id}/tokens
refused).Same as 400 · GET /desks/{id}/tokens
unreachable, unknown_desk).Same as 400 · GET /desks/{id}/tokens
unreachable, with the reach log's reason: silent, closed, …) or could not be woken within wake_s; or it runs a GaiaDesk from before desk operations (protocol, desk_too_old: update GaiaDesk on this desk).Same as 400 · GET /desks/{id}/tokens
rate_limited), or the desk already runs 16 API operations (desk_busy).Same as 400 · GET /desks/{id}/tokens
Retry-Afterintegerconnection_lost), or answered something this server cannot read (protocol).Same as 400 · GET /desks/{id}/tokens
unreachable, desk_ops_disabled).Same as 400 · GET /desks/{id}/tokens
https://api.gaiadesk.net/v1 /desks/{id}/tokens/{token_id} Scope tokensRevoke an agent token; its live sessions and jobs end.
Token administration is the desk OWNER's: a signed-in person's own account on their own desk. An agent token is refused whatever its scopes (403 agent_cannot_admin).
Parameters
idstringpathrequiredtoken_idstringpathrequiredGaiaDesk-E2EstringheaderApiE2eRequest, as base64url of its JSON) in place of a plaintext body or parameters. The answer is then sealed too (ApiE2eAnswer, ApiE2eStreamEvent, ApiE2eFrame). A POST may instead send the body {"e2e": …} (ApiE2eBody). See the "End-to-end encryption" section of docs/api/README.md.wake_sintegerqueryCode samples
cURL
curl -X DELETE "https://api.gaiadesk.net/v1/desks/{id}/tokens/{token_id}" \
-H "Authorization: Bearer $GAIADESK_API_KEY" \
-H "GaiaDesk-E2E: <value>"TypeScript
Python
Go
PHP
Ruby
Java
Responses
Example
{
"revoked": "string",
"stopped_sessions": 0
}Revoked
revokedstringrequiredstopped_sessionsintegerrequired{
"revoked": "string",
"stopped_sessions": 0
}ApiE2eAnswer
e2eobjectrequiredShow child parameters
vintegerrequiredeventsApiE2eFrame[]requiredShow child parameters
seqintegerrequirednoncestringrequiredciphertextstringrequired{
"e2e": {
"v": 0,
"events": [
{
"seq": 0,
"nonce": "string",
"ciphertext": "string"
}
]
}
}X-Request-Idstringreq_…), also in every error body. Quote it to support.RateLimit-LimitintegerRateLimit-RemainingintegerRateLimit-Resetintegerrefused, unauthenticated).Same as 400 · GET /desks/{id}/tokens
refused).Same as 400 · GET /desks/{id}/tokens
unreachable, unknown_desk).Same as 400 · GET /desks/{id}/tokens
unreachable, with the reach log's reason: silent, closed, …) or could not be woken within wake_s; or it runs a GaiaDesk from before desk operations (protocol, desk_too_old: update GaiaDesk on this desk).Same as 400 · GET /desks/{id}/tokens
rate_limited), or the desk already runs 16 API operations (desk_busy).Same as 400 · GET /desks/{id}/tokens
Retry-Afterintegerconnection_lost), or answered something this server cannot read (protocol).Same as 400 · GET /desks/{id}/tokens
unreachable, desk_ops_disabled).Same as 400 · GET /desks/{id}/tokens