REST reference¶
Generated at build time from docs/api/openapi.yaml (Chat Server API, version 0.2.0). Do not edit this page: change the document. Body schemas: Schemas; webhook delivery, signatures and retries: webhooks.
REST API of the team chat with agents that its instance operator hosts.
Normative REST contract of the chat server (spec-first, ADR 0013).
Conventions (names, time, IDs, errors, pagination, idempotency, concurrency, rate limits,
versioning) are in docs/spec/06-api.md. Every operation names its authorization action in
x-authz-action (catalogue docs/spec/05-actions.md) and its rate-limit class in
x-rate-limit-class. The WebSocket gateway is described in asyncapi.yaml; its frame and event
schemas live in components.schemas of this file.
The server never sends JSON null; an absent member means "no value". Clients ignore unknown
members, unknown enum values and unknown event types.
License: Apache-2.0
Servers¶
| URL | Description |
|---|---|
/api/v1 |
Relative to the instance origin. |
Discovery¶
Public metadata, keys and problem types. Health probes are not part of this API (internal listener).
getDiscovery¶
GET /instance/discovery
Public instance metadata
- Security: none
x-authz-action:instance.discovery.readx-rate-limit-class:rl.public_auth
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Discovery |
Correlation-Id, RateLimit, RateLimit-Policy |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"instance_id": "0192f4a0-7b1c-7db7-89b9-2fe4c48dcb3e",
"setup_required": false,
"api_versions": [
"v1"
],
"spec_version": "1.0.0",
"gateway": {
"url": "/api/v1/gateway",
"protocol_versions": [
1
]
},
"branding": {
"product_name": "Team Chat",
"accent_color": "loch",
"logo_url": "/api/v1/instance/branding/logo"
},
"auth_providers": [
{
"id": "0192f4a0-7b1c-7474-8636-4dbb076ee0db",
"kind": "oidc",
"name": "Company SSO"
}
],
"jwks_uri": "/api/v1/instance/jwks",
"webhook_keys_uri": "/api/v1/instance/webhook-keys"
}
getJwks¶
GET /instance/jwks
Public keys for access and invocation tokens
- Security: none
x-authz-action:instance.discovery.readx-rate-limit-class:rl.public_auth
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/jwk-set+json: Jwks |
Correlation-Id, RateLimit, RateLimit-Policy |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"keys": [
{}
]
}
getWebhookKeys¶
GET /instance/webhook-keys
Public keys for webhook signatures
- Security: none
x-authz-action:instance.discovery.readx-rate-limit-class:rl.public_auth
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebhookKeys |
Correlation-Id, RateLimit, RateLimit-Policy |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"keys": [
{
"kid": "whk-2026-10",
"public_key": "whpk_MCowBQYDK2VwAyEA6h3uZ0Q4i1Yv1o1Wg8bQq3c0o8bq9oQm3Kc8n3m3v0I=",
"state": "next"
}
]
}
getBrandingLogo¶
GET /instance/branding/logo
Download the instance logo
Serves the variant medium of the logo (longest edge file.thumbnail.medium_px, re-encoded by the server without metadata, 12 3.7 and 7.3), never the original. Answers 404 while no logo is set and while the logo file is not deliverable (pending, blocked, failed or deleted) or has no variant medium, always with the same status, body and headers. The response carries Content-Disposition: inline, Cache-Control: no-store, ETag and Repr-Digest over the variant and Access-Control-Allow-Origin: * without credentials; Range is ignored.
- Security: none
x-authz-action:instance.discovery.readx-rate-limit-class:rl.public_auth
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | image/*: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getProblemType¶
GET /problems/{code}
Documentation of a problem type
- Security: none
x-authz-action:instance.discovery.readx-rate-limit-class:rl.public_auth
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
code |
path | string | yes | Pattern ^[a-z0-9_]+$. Example: version_conflict. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ProblemType |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"code": "version_conflict",
"status": 412,
"title": "Version conflict",
"description": "Support team"
}
submitCspReport¶
POST /csp-reports
Accept a CSP violation report of the web console
Endpoint of report-to csp and of Reporting-Endpoints: csp="/api/v1/csp-reports" on every console response (19-security 5 rule 6, R-AZ-33). Public, because browsers send reports without cookies in many cases; a console cookie is not checked by the CSRF guard here, the action changes nothing. Accepts the Reporting API format (application/reports+json, an array of reports) and the legacy report-uri format (application/csp-report), both limited by http.max_json_body_bytes. The server stores no report; it logs only the effective directive, the disposition and the origin of the blocked URL and counts bothy.console.csp_violations. Members it does not read are ignored.
- Security: none
x-authz-action:console.csp_reportx-rate-limit-class:rl.public_authx-idempotency-exempt:telemetry
Request body (required): application/reports+json: CspReportListapplication/csp-report: CspReportLegacy
Reporting API
[
{
"type": "csp-violation",
"age": 10,
"url": "https://chat.example.com/console/",
"body": {
"documentURL": "https://chat.example.com/console/",
"blockedURL": "https://cdn.example.com/x.js",
"effectiveDirective": "script-src-elem",
"disposition": "enforce"
}
}
]
Legacy report-uri
{
"csp-report": {
"document-uri": "https://chat.example.com/console/",
"blocked-uri": "inline",
"effective-directive": "script-src-elem",
"disposition": "enforce"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Report accepted (also when it names nothing the server logs). | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 415 | UnsupportedMediaType: Problem codes: unsupported_media_type. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Auth¶
Login flows, token refresh with DPoP, logout and step-up.
beginOidcLogin¶
POST /auth/oidc/begin
Start an OIDC login
- Security: none
x-authz-action:auth.login.beginx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Request body (required): application/json: OidcBeginRequest
Request
{
"provider_id": "0192f4a0-7b1c-7b3c-87cd-dea30414c03e",
"app_redirect_uri": "com.example.teamchat:/login",
"client_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: OidcBeginResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"login_attempt_id": "0192f4a0-7b1c-74de-8f28-b1bfbb9fa235",
"authorization_url": "https://login.example.com/authorize?client_id=chat&state=s1",
"expires_at": "2026-10-10T09:30:00.000Z"
}
handleOidcCallback¶
GET /auth/oidc/callback
OIDC redirect target of the identity provider
Exchanges the code at the provider and verifies the ID token. It stores only the verified external identity in the login flow; mapping, linking and provisioning happen at completeOidcLogin (08, 2.2). Then it redirects to app_redirect_uri with the query parameters login_code (one-time, valid auth.server_code_ttl) and login_attempt_id. After the flow was found, every failure redirects with error and login_attempt_id; error is one of access_denied (the provider sent an error), login_failed (a check failed) and flow_expired. An unknown or expired state gets 400 without a redirect.
- Security: none
x-authz-action:auth.login.beginx-rate-limit-class:rl.public_auth
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
state |
query | string | yes | State from the authorization request. |
iss |
query | string | no | Issuer of the authorization response (RFC 9207). Required when the provider announces authorization_response_iss_parameter_supported. |
code |
query | string | no | Authorization code. |
error |
query | string | no | Error code from the provider. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 302 | Redirect to app_redirect_uri with login_code and login_attempt_id, or with error and login_attempt_id. |
Correlation-Id, RateLimit, RateLimit-Policy, Location | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
completeOidcLogin¶
POST /auth/oidc/complete
Finish an OIDC login and register the device
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | no | As DpopProof; not for client = console. |
Request body (required): application/json: OidcCompleteRequest
Request
{
"login_code": "lc_8f2d1c",
"client_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | ConsoleLogin: Console session (08, 7.5). | application/json: ConsoleSession |
Correlation-Id, Set-Cookie |
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
loginWithTrustedHeader¶
POST /auth/trusted-header/login
Log in with the identity header of a trusted reverse proxy
Only enabled when the server listens on loopback and a trusted_header provider is active;
otherwise 404.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | no | As DpopProof; not for client = console. |
Request body (required): application/json: TrustedHeaderLoginRequest
Request
{
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | ConsoleLogin: Console session (08, 7.5). | application/json: ConsoleSession |
Correlation-Id, Set-Cookie |
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
beginPasskeyLogin¶
POST /auth/passkey/begin
Start a passkey login
Starts a passkey login. The ceremony state is stored on the server (auth_challenges) and is valid once for auth.login_flow_ttl. Only people with an active identity of the local driver can log in with a passkey. For an unknown login name the options carry one decoy credential ID derived by HMAC, so the answer reveals no accounts.
- Security: none
x-authz-action:auth.login.beginx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Request body (required): application/json: PasskeyLoginBeginRequest
Request
{
"login_name": "alex"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebAuthnChallenge |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"public_key": {},
"expires_at": "2026-10-10T09:30:00.000Z"
}
completePasskeyLogin¶
POST /auth/passkey/complete
Finish a passkey login and register the device
Completes a passkey login with a DPoP proof of the device key. A new device stays pending until approved; a known active device stays active. Every rejection gives the same 401 body.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | no | As DpopProof; not for client = console. |
Request body (required): application/json: PasskeyLoginCompleteRequest
Request
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"credential": {},
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | ConsoleLogin: Console session (08, 7.5). | application/json: ConsoleSession |
Correlation-Id, Set-Cookie |
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
beginEnrollment¶
POST /auth/enroll/begin
Start the first passkey registration with an enrollment code
Starts the first passkey registration with an enrollment code of purpose first_login or recovery. The code is checked but not redeemed; the stored challenge keeps a reference to it. Every rejected code gives 401.
- Security: none
x-authz-action:auth.login.beginx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Request body (required): application/json: EnrollBeginRequest
Request
{
"enrollment_code": "en_4KX9-2MQA"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebAuthnChallenge |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"public_key": {},
"expires_at": "2026-10-10T09:30:00.000Z"
}
completeEnrollment¶
POST /auth/enroll/complete
Register the first passkey and log in
Registers the first passkey and logs in; the enrollment code of the challenge is redeemed in the same transaction and the device becomes active. A failed verification counts as a failed attempt of the code. Every rejection gives 401.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | yes | DPoP proof (RFC 9449) signed with the device key that the new tokens will be bound to. |
Request body (required): application/json: EnrollCompleteRequest
Request
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"credential": {},
"passkey_name": "Laptop",
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
redeemEnrollmentCode¶
POST /auth/enroll/redeem
Redeem an enrollment code with device keys and log in
Redeems an enrollment code without a passkey; the redeeming device becomes active (08, 3.2). Every rejected code (unknown, used, expired, exhausted, wrong purpose, person not active) gets the same 401 body. Code and device keys are checked in one transaction; a failed attempt with a matching code counts against auth.enrollment_code_max_attempts.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | yes | DPoP proof (RFC 9449) signed with the device key that the new tokens will be bound to. |
Request body (required): application/json: EnrollRedeemRequest
Request
{
"enrollment_code": "en_EXAMPLE",
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "enrollment_code",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
beginPairing¶
POST /auth/pairing/begin
Start a device pairing without login
The new device registers its public keys and shows the returned code. An active device of the same person approves it with approvePairing (08, 5.3).
- Security: none
x-authz-action:auth.login.beginx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | yes | DPoP proof (RFC 9449) signed with the device key that the new tokens will be bound to. |
Request body (required): application/json: PairingBeginRequest
Request
{
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex Laptop",
"platform": "macos",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256",
"step_up_key": {
"public_jwk": {},
"alg": "ES256"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: PairingStarted |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"pairing_id": "0192f4a0-7b1c-7e21-8f3a-5b6c7d8e9f10",
"pairing_code": "7KQ2-M9XD",
"expires_at": "2026-10-10T09:35:00.000Z"
}
completePairing¶
POST /auth/pairing/complete
Collect the tokens of an approved pairing
The DPoP proof must be signed with the dpop key registered at beginPairing; a proof signed by another key rejects the pairing. Before approval the answer is 202 with the status; after expiry or rejection 410.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | yes | DPoP proof (RFC 9449) signed with the device key that the new tokens will be bound to. |
Request body (required): application/json: PairingCompleteRequest
Request
{
"pairing_id": "0192f4a0-7b1c-7e21-8f3a-5b6c7d8e9f10"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 202 | Not yet approved. | application/json: PairingStatus |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "device_pairing",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex Laptop",
"platform": "macos",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
loginWithPassword¶
POST /auth/password/login
Log in with local password and TOTP
Fallback for local accounts. 404 when auth.local_password_enabled is false. A new device stays pending until approved (08, 5.2). Unknown names, wrong passwords and locked accounts give the same 401.
- Security: none
x-authz-action:auth.login.completex-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | no | As DpopProof; not for client = console. |
Request body (required): application/json: PasswordLoginRequest
Request
{
"login_name": "alex",
"password": "example-password",
"totp_code": "492039",
"device": {
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"name": "Alex iPhone",
"platform": "ios",
"app_version": "1.4.0",
"public_jwk": {},
"alg": "ES256"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | ConsoleLogin: Console session (08, 7.5). | application/json: ConsoleSession |
Correlation-Id, Set-Cookie |
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
refreshToken¶
POST /auth/token/refresh
Rotate the refresh token
The DPoP proof must use the device key of the session. Reuse of an already rotated token revokes
the token family and the session (session_revoked), except within auth.refresh_reuse_grace
with the same key. In maintenance mode (server.maintenance_mode = read_only, ADR 0065) the
server issues a new access token and returns the same refresh token, without rotation.
- Security: none
x-authz-action:auth.token.refreshx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
DPoP |
header | string | yes | DPoP proof (RFC 9449) signed with the device key that the new tokens will be bound to. |
Request body (required): application/json: TokenRefreshRequest
Request
{
"refresh_token": "rt_q2Z0"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
logout¶
POST /auth/logout
End the current session
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.logoutx-rate-limit-class:rl.writex-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, Set-Cookie, RateLimit, RateLimit-Policy | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
createStepUpChallenge¶
POST /auth/step-up/challenge
Create a step-up challenge
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StepUpChallenge |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"challenge": "Zm9vYmFyYmF6",
"expires_at": "2026-10-10T09:30:00.000Z"
}
completeStepUpWithPasskey¶
POST /auth/step-up/passkey
Confirm step-up with a passkey
Completes a step-up with a passkey assertion over the step-up challenge. A passkey of another person fails and counts toward auth.step_up_fail_limit.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Request body (required): application/json: StepUpPasskeyRequest
Request
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"credential": {}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | StepUpDone: OK; a console session gets a new cookie (08, 7.5). | application/json: StepUpResult |
Correlation-Id, Set-Cookie |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
completeStepUpWithDeviceKey¶
POST /auth/step-up/device-key
Confirm step-up with the device key after user verification
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Request body (required): application/json: StepUpDeviceKeyRequest
Request
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"signature": "eyJhbGciOiJFUzI1NiJ9.eyJjIjoiWm05dlltRnlZbUY2In0.sig"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StepUpResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"step_up_at": "2026-10-10T09:30:00.000Z",
"valid_until": "2026-10-10T09:30:00.000Z"
}
stepUpWithPassword¶
POST /auth/step-up/password
Console step-up with password and TOTP
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Request body (required): application/json: StepUpPasswordRequest
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | StepUpDone: OK; a console session gets a new cookie (08, 7.5). | application/json: StepUpResult |
Correlation-Id, Set-Cookie |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
beginStepUpOidcReauth¶
POST /auth/step-up/oidc
Start a console step-up with OIDC
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Request body (required): application/json: StepUpOidcBeginRequest
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: OidcBeginResponse |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
completeStepUpOidcReauth¶
POST /auth/step-up/oidc/complete
Finish a console step-up with OIDC
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:auth.step_upx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Request body (required): application/json: IdentityLinkComplete
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | StepUpDone: OK; a console session gets a new cookie (08, 7.5). | application/json: StepUpResult |
Correlation-Id, Set-Cookie |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getConsoleSession¶
GET /console/session
Read the console session
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:self.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | ConsoleLogin: Console session (08, 7.5). | application/json: ConsoleSession |
Correlation-Id, Set-Cookie |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
endViewAs¶
DELETE /console/session/view-as
End the stored view as person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.view_as.endx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Console-Request |
header | string | no | CSRF header of the console (SEC-CORS-4). Values: 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Me¶
The calling principal: profile, credentials, mentions, personal templates.
getMe¶
GET /me
Read the calling principal
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:self.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Me |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"principal": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"is_owner": false,
"email": "alex@example.com",
"locale": "de",
"time_zone": "Europe/Berlin",
"permission_version": 1
}
updateMyProfile¶
PATCH /me/profile
Change own profile
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:self.profile.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ProfileUpdate
Request
{
"display_name": "Alex",
"locale": "de",
"time_zone": "Europe/Berlin"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
setMyAvatar¶
PUT /me/avatar
Upload own avatar
Only for people; nothing of the body is read before authorize allowed the action. Checks in this order (12 3.7): the first part is file (400 validation_failed); the declared type is JPEG, PNG or WebP (415 unsupported_media_type, with reason file_type_denied for a type in file.denied_mime_types); the part holds at most the smaller of file.max_upload_bytes and file.upload_part_bytes (413 payload_too_large) and at least one byte, and no further part follows (400 validation_failed); open sessions (429) and free space of the file system driver (503 unavailable with reason storage_full). The new file is linked at once (avatar_file_id) and replaces the previous avatar; it becomes deliverable later, after scan and metadata removal, and until then file downloads answer 409 file_not_ready.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:self.profile.updatex-rate-limit-class:rl.write
Request body (required): multipart/form-data: ImageUpload
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 415 | UnsupportedMediaType: Problem codes: unsupported_media_type. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
deleteMyAvatar¶
DELETE /me/avatar
Remove own avatar
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:self.profile.updatex-rate-limit-class:rl.write
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getMyCredentials¶
GET /me/credentials
List own identities and passkeys
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CredentialOverview |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"identities": [
{
"id": "0192f4a0-7b1c-7dd2-83b9-528d363b749b",
"provider_id": "0192f4a0-7b1c-7b3c-87cd-dea30414c03e",
"provider_kind": "oidc",
"subject": "alex",
"issuer": "https://login.example.com",
"linked_at": "2026-10-10T09:30:00.000Z"
}
],
"passkeys": [
{
"id": "0192f4a0-7b1c-7ad4-8a99-f31c00005918",
"name": "Laptop",
"backup_eligible": false,
"created_at": "2026-10-10T09:30:00.000Z"
}
],
"local_password_set": false,
"totp_enrolled": false
}
beginIdentityLink¶
POST /me/identities/begin
Start linking another identity
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity.linkx-rate-limit-class:rl.adminx-idempotency-exempt:auth_flow
Request body (required): application/json: IdentityLinkBegin
Request
{
"provider_id": "0192f4a0-7b1c-7b3c-87cd-dea30414c03e",
"app_redirect_uri": "com.example.teamchat:/link",
"client_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: OidcBeginResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"login_attempt_id": "0192f4a0-7b1c-74de-8f28-b1bfbb9fa235",
"authorization_url": "https://login.example.com/authorize?client_id=chat&state=s1",
"expires_at": "2026-10-10T09:30:00.000Z"
}
completeIdentityLink¶
POST /me/identities/complete
Finish linking another identity
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity.linkx-rate-limit-class:rl.adminx-idempotency-exempt:auth_flow
Request body (required): application/json: IdentityLinkComplete
Request
{
"login_code": "lc_8f2d1c",
"client_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Identity |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7dd2-83b9-528d363b749b",
"provider_id": "0192f4a0-7b1c-7b3c-87cd-dea30414c03e",
"provider_kind": "oidc",
"subject": "alex",
"issuer": "https://login.example.com",
"linked_at": "2026-10-10T09:30:00.000Z"
}
beginPasskeyRegistration¶
POST /me/passkeys/begin
Start registering a passkey
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:passkey.registerx-rate-limit-class:rl.adminx-idempotency-exempt:auth_flow
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebAuthnChallenge |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"public_key": {},
"expires_at": "2026-10-10T09:30:00.000Z"
}
completePasskeyRegistration¶
POST /me/passkeys/complete
Finish registering a passkey
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:passkey.registerx-rate-limit-class:rl.adminx-idempotency-exempt:auth_flow
Request body (required): application/json: PasskeyRegisterComplete
Request
{
"challenge_id": "0192f4a0-7b1c-747c-835d-13eca158d3c0",
"credential": {},
"name": "Laptop"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Passkey |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7ad4-8a99-f31c00005918",
"name": "Laptop",
"backup_eligible": false,
"created_at": "2026-10-10T09:30:00.000Z"
}
setMyLocalCredential¶
PUT /me/local-credential
Set local password and enroll TOTP
Needs a local identity (else 409 conflict) and auth.local_password_enabled (else 403 feature_disabled). Step-up is required once the password path is established (TOTP confirmed, 07 4.2 step 8). The TOTP URI in the response is shown once; the call is a PUT and stores no response.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:local_credential.setx-rate-limit-class:rl.admin
Request body (required): application/json: LocalCredentialSet
Request
{
"password": "example-password"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: LocalCredentialResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"password_set": true,
"totp_enabled": false,
"totp_secret_uri": "otpauth://totp/Team%20Chat:alex?secret=JBSWY3DPEHPK3PXP"
}
listMyMentions¶
GET /me/mentions
List own mentions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:mention.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: MentionItemPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"message": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
},
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
listMyTemplates¶
GET /me/templates
List own personal templates
Personal templates of the caller, without a channel context. Channel templates come from listTemplates.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TemplateList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-777d-8541-d21a5b1c8fe4",
"scope": "personal",
"name": "Escalation",
"content_md": "Please escalate this ticket to second level.",
"version": 3
}
]
}
createPersonalTemplate¶
POST /me/templates
Create a personal template
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.managex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: TemplateCreate
Request
{
"name": "Escalation",
"content_md": "Please escalate this ticket to second level."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Template |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-777d-8541-d21a5b1c8fe4",
"scope": "personal",
"name": "Escalation",
"content_md": "Please escalate this ticket to second level.",
"version": 3
}
Users¶
People and owners.
listUsers¶
GET /users
List people
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
q |
query | string | no | Prefix match on handle or display name. |
status |
query | UserStatus | no | Filter by status. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UserPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createUser¶
POST /users
Create a person
With local_account the server creates the local identity (subject = handle) and a first_login enrollment code. The code is a one-time secret: a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret (06, 7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: UserCreate
Request
{
"handle": "robin",
"display_name": "Robin",
"email": "robin@example.com",
"locale": "de",
"time_zone": "Europe/Berlin"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: UserCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
getUser¶
GET /users/{user_id}
Read a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
updateUser¶
PATCH /users/{user_id}
Change another person's profile
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: UserUpdate
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
disableUser¶
POST /users/{user_id}/disable
Disable a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.disablex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
enableUser¶
POST /users/{user_id}/enable
Enable a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.enablex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: User |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"locale": "en",
"time_zone": "Europe/Berlin",
"created_at": "2026-10-10T09:30:00.000Z"
}
createEnrollmentCode¶
POST /users/{user_id}/enrollment-codes
Issue an enrollment code
Issues a code for an active person: first_login for a person with a local identity and no device yet, recovery for a person with a local identity and a device, identity_link for a person without a local identity (08, 3.2). Issuing ends every other unused code of the person. The code is a one-time secret: a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret instead of repeating it (06, 7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: EnrollmentCode |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"code": "en_4KX9-2MQA",
"purpose": "first_login",
"expires_at": "2026-10-10T09:30:00.000Z"
}
getUserCredentials¶
GET /users/{user_id}/credentials
List identities and passkeys of a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CredentialOverview |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"identities": [
{
"id": "0192f4a0-7b1c-7dd2-83b9-528d363b749b",
"provider_id": "0192f4a0-7b1c-7b3c-87cd-dea30414c03e",
"provider_kind": "oidc",
"subject": "alex",
"issuer": "https://login.example.com",
"linked_at": "2026-10-10T09:30:00.000Z"
}
],
"passkeys": [
{
"id": "0192f4a0-7b1c-7ad4-8a99-f31c00005918",
"name": "Laptop",
"backup_eligible": false,
"created_at": "2026-10-10T09:30:00.000Z"
}
],
"local_password_set": false,
"totp_enrolled": false
}
unlinkIdentity¶
DELETE /users/{user_id}/identities/{identity_id}
Unlink an identity
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity.unlinkx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
identity_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
revokePasskey¶
DELETE /users/{user_id}/passkeys/{passkey_id}
Revoke a passkey
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:passkey.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
passkey_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listOwners¶
GET /owners
List owners
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:user.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: OwnerList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"granted_at": "2026-10-10T09:30:00.000Z",
"reason": "Requested by the space lead"
}
]
}
addOwner¶
POST /owners
Make a person owner
Optional resolve_i1 runs the guided flow (05 rule 1.6, 10 section 11): the listed agents are authorized with agent.billing_mode.set and switched to organization first, in the same transaction as the change; I1 is checked before the commit, and either both parts commit or none.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:owner.addx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: OwnerAdd
Request
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"reason": "Second owner as deputy"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Owner |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"granted_at": "2026-10-10T09:30:00.000Z",
"reason": "Requested by the space lead"
}
revokeOwner¶
POST /owners/{user_id}/revoke
Remove the owner role
Fails with last_owner when no other active owner remains and with i1_violation when I1 would
break.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:owner.removex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Devices¶
Devices, sessions and push targets.
listUserDevices¶
GET /users/{user_id}/devices
List devices of a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: DevicePage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
listUserSessions¶
GET /users/{user_id}/sessions
List sessions of a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:session.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SessionPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
}
]
}
listMyDevices¶
GET /me/devices
List own devices
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: DevicePage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
approvePairing¶
POST /me/devices/pairings
Approve a device pairing with its code
Called from an active device of the person, with step-up. Creates the new device as active for the calling person; the new device collects its tokens with completePairing within auth.pairing_code_ttl, otherwise it is revoked. A code that matches no open pairing answers 404 and ends the step-up of the calling session, so every further attempt needs a new confirmation with biometrics.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.approvex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: PairingApprove
Request
{
"pairing_code": "7KQ2-M9XD"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Device |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex Laptop",
"platform": "macos",
"state": "active",
"created_at": "2026-10-10T09:30:00.000Z"
}
getDevice¶
GET /devices/{device_id}
Read a device
A pending device polls this to learn when it was approved.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
device_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Device |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
approveDevice¶
POST /devices/{device_id}/approve
Approve a pending device
The approving person types the verification code shown on the pending device (08, 5.2). A wrong code revokes the pending device; the answer is then 200 with state revoked, because the request had an effect.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.approvex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
device_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: DeviceApprove
Request
{
"verification_code": "042517"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Device |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
revokeDevice¶
POST /devices/{device_id}/revoke
Revoke a device
Closes its gateway connections with 4012 and revokes its sessions.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:device.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
device_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Device |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
registerPush¶
POST /me/devices/current/push-registrations
Register a push target for the current device
Registers the push target of the caller's own active device in the caller's session and returns the preview token of the registration exactly once (13, 6.4 and 13). The row binds the person, the device and the session. A known (provider, token) is taken over: its row is deleted, whoever it belonged to, so the token stops reaching its former owner; the other active registrations of this device with the same provider and app_id end with disabled_reason token_invalid (one current token per app installation). Every new registration rotates the preview token. unifiedpush and wns give 400 validation_failed with errors[].code not_enabled; apns or fcm without a configured adapter on this instance give 403 feature_disabled with reason push_provider_disabled; a principal without a session (API tokens, agents, apps) gives 403 forbidden with reason step_up_not_possible; a pending device gives 403 device_pending. The preview token is a one-time secret: a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret (06, 7), and the app registers again with a new key. A second concurrent registration of the same token can answer 409 conflict.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:push.registerx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: PushRegistrationCreate
Request
{
"provider": "fcm",
"token": "EXAMPLE-device-token-a1b2",
"app_id": "com.example.teamchat"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: PushRegistrationCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72f6-893c-a890548910a3",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"provider": "fcm",
"environment": "production",
"app_id": "com.example.teamchat",
"created_at": "2026-10-10T09:30:00.000Z",
"preview_token": "bothy_pvw_EXAMPLEpushpreviewtoken00000000000000000000_4Z1L0A"
}
unregisterPush¶
DELETE /push-registrations/{registration_id}
Remove a push target
Deletes a registration of the caller (13, 13). The token is free for a later registration and the preview token of the registration is worthless from then on. A registration of another person and an unknown one give the same 404.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:push.unregisterx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
registration_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getPushPreview¶
GET /push/preview
Load the preview of a notification
Called by the notification extension with the preview token of the push registration (Authorization: DPoP <token>) and a DPoP proof of the device key whose ath is the hash of the preview token; no other operation accepts the token, and no other credential works here (13, 6.4; R-PN-07). Checks in this order: the parameter kind; exactly one Authorization value with the scheme DPoP; the form, kind pvw and checksum of the token without a database access; an active registration with the token; the session of the registration, whose device must be the device of the registration; the DPoP proof against the key of that session (DPoP-Nonce as on every DPoP request); then message.read on the message and push.deliver on its thread with the rights of the moment of the fetch. A missing, malformed or unknown token, a deactivated registration, a session that is unknown or belongs to another device and a wrong proof give 401; while the registration is still active, a session, device or person that is no longer active (for example an expired session) gives 401 session_revoked. auth.logout, device.revoke and user.disable deactivate the registration in their own transaction, so after them the token itself answers 401. No right, a deleted or an unknown message give 404, identical to each other. The answer follows notify.preview_mode of the person (13, 6.4 table): full with names, excerpt (text without Markdown, mentions as names, at most notify.preview_max_chars), attachment_count and image_url (a fetch ticket for the small thumbnail of the first image); names with the four names only; none only kind, thread_id, message_id and badge.
- Security: pushPreviewToken
x-authz-action:message.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
nid |
query | Uuid | yes | Notification ID from the push. |
message_id |
query | Uuid | yes | Message of the notification. |
kind |
query | NotificationKind | yes | Kind of the notification, copied from the push payload (k, 13, 6.1 and 6.2). The server keeps no record of a hint, so the kind selects only the labels on the device; the answer echoes it. Only the kinds that point at a message are allowed; security and admin give 400 validation_failed with errors[].code invalid at #query/kind, before the token is checked. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: PushPreview |
Correlation-Id, RateLimit, RateLimit-Policy, DPoP-Nonce |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"kind": "mention",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"badge": 3,
"space_name": "Support",
"channel_name": "tickets",
"thread_title": "Invoice export fails",
"sender_display_name": "Alex",
"excerpt": "Sam can you check the export?"
}
listMySessions¶
GET /me/sessions
List own sessions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:session.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SessionPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
}
]
}
createExtensionSession¶
POST /me/sessions/extensions
Create a child session for an app extension
Creates a child session of the calling app session for the notification or share extension, with its own refresh family on the same device key (08, 7.4). An active child of the same component is replaced. The refresh token is shown once; the request carries no Idempotency-Key because a repeat only replaces the child.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:session.extension.createx-rate-limit-class:rl.writex-idempotency-exempt:auth_flow
Request body (required): application/json: ExtensionSessionCreate
Request
{
"client_component": "share_ext"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: TokenResponse |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"access_token": "eyJhbGciOiJFZERTQSJ9.e30.sig",
"token_type": "DPoP",
"expires_in": 900,
"refresh_token": "rt_q2Z0",
"refresh_expires_at": "2026-10-10T09:30:00.000Z",
"session": {
"id": "0192f4a0-7b1c-75c3-8a09-bf22e12411b6",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"auth_method": "oidc",
"client_component": "share_ext",
"created_at": "2026-10-10T09:30:00.000Z",
"expires_at": "2026-10-10T09:30:00.000Z"
},
"device": {
"id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Alex iPhone",
"platform": "ios",
"state": "active",
"app_version": "1.4.0",
"key_thumbprint": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
revokeSession¶
POST /sessions/{session_id}/revoke
End a session
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:session.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
session_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Tokens¶
API tokens of agents, apps and personal tools.
listTokens¶
GET /principals/{principal_id}/tokens
List API tokens of a principal
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:token.listx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
principal_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ApiTokenPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-703d-85ae-fdc884c55554",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Adapter production",
"token_prefix": "bothy_agt_EXAMPL",
"scopes": [],
"dpop_jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"expires_at": "2027-10-10T00:00:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createToken¶
POST /principals/{principal_id}/tokens
Create an API token
Kind follows the principal (agt agent, app app, pat person, 08 section 12). A personal token only for oneself and only with the flag tokens.personal_enabled. A token for an app needs an active installation (else 409 conflict with reason app_not_installed, also while the app is suspended); its scopes are the requested subset of the granted scopes of the installation, or all of them when scopes is absent or empty, and a scope the installation does not grant gives 400 validation_failed at /scopes/<i>. An app request needs the scope of its action in the token and in the installation. The secret is shown once; a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret (06, 7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:token.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
principal_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ApiTokenCreate
Request
{
"name": "Adapter production",
"dpop_jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"expires_at": "2027-10-10T00:00:00.000Z"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: ApiTokenCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"token": {
"id": "0192f4a0-7b1c-703d-85ae-fdc884c55554",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "Adapter production",
"token_prefix": "bothy_agt_EXAMPL",
"scopes": [],
"dpop_jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I",
"expires_at": "2027-10-10T00:00:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
},
"secret": "bothy_agt_EXAMPLEOnlyNotARealTokenForTheChecksumTests_3NymP3"
}
revokeToken¶
DELETE /tokens/{token_id}
Revoke an API token
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:token.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
token_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Groups¶
Groups of people as grant subjects.
listGroups¶
GET /groups
List groups
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
member_id |
query | Uuid | no | Only groups with this member. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GroupPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7abf-88a6-0fbb818f7405",
"name": "Support",
"description": "Support team",
"source": "local",
"member_count": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createGroup¶
POST /groups
Create a group
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GroupCreate
Request
{
"name": "Support"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Group |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7abf-88a6-0fbb818f7405",
"name": "Support",
"description": "Support team",
"source": "local",
"member_count": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
getGroup¶
GET /groups/{group_id}
Read a group
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Group |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7abf-88a6-0fbb818f7405",
"name": "Support",
"description": "Support team",
"source": "local",
"member_count": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
deleteGroup¶
DELETE /groups/{group_id}
Delete a group and revoke its grants
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.deletex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateGroup¶
PATCH /groups/{group_id}
Rename a group
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GroupUpdate
Request
{
"name": "Support"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Group |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7abf-88a6-0fbb818f7405",
"name": "Support",
"description": "Support team",
"source": "local",
"member_count": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
listGroupMembers¶
GET /groups/{group_id}/members
List members
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GroupMemberPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"added_at": "2026-10-10T09:30:00.000Z"
}
]
}
addGroupMember¶
POST /groups/{group_id}/members
Add a member
Optional resolve_i1 runs the guided flow (05 rule 1.6, 10 section 11): the listed agents are authorized with agent.billing_mode.set and switched to organization first, in the same transaction as the change; I1 is checked before the commit, and either both parts commit or none.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.member.addx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GroupMemberAdd
Request
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: GroupMember |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"added_at": "2026-10-10T09:30:00.000Z"
}
removeGroupMember¶
DELETE /groups/{group_id}/members/{user_id}
Remove a member
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:group.member.removex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
group_id |
path | Uuid | yes | |
user_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Access¶
Grants, grant preview, who has access, view as person.
viewAsUser¶
GET /users/{user_id}/view-as
See the instance as a person sees it
Owner only, with step-up and audit. Returns the spaces and channels the person sees, with level and the end of the view (authz.view_as_max_duration). The person's direct messages stay invisible (SR6). In M1 the view lives only within this request (07, 9.2).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.view_asx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
user_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ViewAsSnapshot |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"expires_at": "2026-10-10T09:45:00.000Z",
"spaces": [
{
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
],
"channels": [
{
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
]
}
listGrants¶
GET /grants
List grants of a target or subject
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:grant.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
target_kind |
query | TargetKind | no | Target kind. |
target_id |
query | Uuid | no | Target ID. |
subject_kind |
query | GrantSubjectKind | no | Subject kind. |
subject_id |
query | Uuid | no | Subject ID. |
include_revoked |
query | boolean | no | Include revoked and expired grants. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GrantPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-727f-86bd-90fe7bdb3024",
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"capabilities": [
"approve_actions"
],
"reason": "Support team works in this space",
"granted_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"granted_at": "2026-10-10T09:30:00.000Z"
}
]
}
createGrant¶
POST /grants
Create a grant
Optional resolve_i1 runs the guided flow (05 rule 1.6, 10 section 11): the listed agents are authorized with agent.billing_mode.set and switched to organization first, in the same transaction as the change; I1 is checked before the commit, and either both parts commit or none.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:grant.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GrantCreate
Request
{
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"reason": "Support team works in this space"
}
Switch the operator to organization first (guided flow)
{
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "channel",
"target_id": "0192f4a0-7b1c-7a3d-9f1e-2b4c6d8e0a12",
"level": "trigger",
"reason": "Sam works in the research notes",
"resolve_i1": {
"switch_to_organization": [
"0192f4a0-7b1c-7c55-8e21-3f5a7b9d1c34"
],
"reason": "Sam triggers the assistant too"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Grant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-727f-86bd-90fe7bdb3024",
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"capabilities": [
"approve_actions"
],
"reason": "Support team works in this space",
"granted_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"granted_at": "2026-10-10T09:30:00.000Z"
}
previewGrant¶
POST /grants/preview
Show what a grant would change
Dry run of createGrant (action access.preview): affected principals, level changes and
invariant violations. No step-up needed; the transaction is rolled back, nothing is stored.
The caller needs read access to the target (else 404) and owner or manage on it (else
403); limits of delegation give 200 with allowed: false and denial_reason. text
is in the caller's language (de or en, else de) with dates in the caller's time zone
(07, 9.3). With resolve_i1 the preview is a dry run of the whole guided flow: every listed
agent needs access.preview with the target action agent.billing_mode.set (owner, no
step-up; an unknown or invisible agent gives 404), the agents are switched to
organization before the grant, and text names each agent the request would switch.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.previewx-rate-limit-class:rl.adminx-idempotency-exempt:read_only
Request body (required): application/json: GrantCreate
Request
{
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"reason": "Support team works in this space"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GrantPreview |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"allowed": true,
"effects": [
{
"principal": {
"id": "0192f4a0-7b1c-733c-835c-6d67630008cd",
"kind": "user",
"handle": "sam",
"display_name": "Sam"
},
"target_kind": "channel",
"target_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"before_level": "none",
"after_level": "trigger",
"capabilities_added": []
}
],
"invariant_violations": [],
"hints": [
{
"code": "read_horizon",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"principal_id": "0192f4a0-7b1c-733c-835c-6d67630008cd",
"channel_id": "0192f4a0-7b1c-7c2a-8e1d-41a6b2c3d4e5"
}
],
"text": "Sam gets the level \"Trigger\" in channel Marketing/Kampagnen until 2026-12-31.\nSam can then: read and write messages, create threads, trigger agent Texter.\nUpload files: no. Confirm approval cards: no.\nNote: Texter also reads Marketing/Intern. Sam may not read Marketing/Intern but can learn its contents through Texter.",
"text_locale": "en"
}
getGrant¶
GET /grants/{grant_id}
Read a grant
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:grant.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
grant_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Grant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-727f-86bd-90fe7bdb3024",
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"capabilities": [
"approve_actions"
],
"reason": "Support team works in this space",
"granted_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"granted_at": "2026-10-10T09:30:00.000Z"
}
revokeGrant¶
POST /grants/{grant_id}/revoke
Revoke a grant
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:grant.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
grant_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Grant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-727f-86bd-90fe7bdb3024",
"subject_kind": "user",
"subject_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"target_kind": "instance",
"level": "read",
"capabilities": [
"approve_actions"
],
"reason": "Support team works in this space",
"granted_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"granted_at": "2026-10-10T09:30:00.000Z"
}
explainSpaceAccess¶
GET /spaces/{space_id}/access
Who has access to a space
Every principal with access and the chain of sources (direct, group, inherited, operator, via agent, blocked by a guard rule). An entry only through an agent has level none; disabled principals are marked inactive (07, 9.1).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.explainx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AccessExplanation |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"target_kind": "space",
"target_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"entries": [
{
"principal": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"level": "read",
"capabilities": [
"approve_actions"
],
"sources": [
{
"kind": "owner"
}
]
}
]
}
explainChannelAccess¶
GET /channels/{channel_id}/access
Who has access to a channel
Every principal with access and the chain of sources (direct, group, inherited, operator, direct-message participant, via agent, blocked by a guard rule). An entry only through an agent has level none; disabled principals are marked inactive (07, 9.1).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.explainx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AccessExplanation |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"target_kind": "space",
"target_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"entries": [
{
"principal": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"level": "read",
"capabilities": [
"approve_actions"
],
"sources": [
{
"kind": "owner"
}
]
}
]
}
listPermissionHints¶
GET /access/hints
List the permission hints
The list "Permission hints" of 07 section 9.5, computed from the permission state that authorize uses: h1_read_horizon for every agent, person of its trigger set and channel of its read horizon the person cannot read (07 section 6), grant_to_disabled for grants whose subject is disabled, trigger_blocked for trigger grants whose triggering SR2 or SR3 blocks on every operated channel they reach, agent_personal for agents in mode personal with their trigger set. Ordered by kind in this order, then by agent, person and channel, by grant ID or by agent ID. Without space_id the instance (owners); with it the space (owner or manage), limited to its agents, channels and grants. A space the caller cannot read gives 404, readable without manage 403. Hints never name content; labels carries the names of the principals, groups, spaces and channels of the page.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.hints.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
space_id |
query | Uuid | no | Only the hints of this space; without it the whole instance (owners only). |
kind |
query | PermissionHintKind | no | Only hints of this kind. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: PermissionHintPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"kind": "h1_read_horizon",
"agent_id": "0192f4a0-7b1c-7a11-8c2e-1d4e5f6a7b8c",
"person_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bd",
"space_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"channel_id": "0192f4a0-7b1c-7c33-9e4f-2a3b4c5d6e7f"
}
],
"labels": {
"principals": [
{
"id": "0192f4a0-7b1c-7a11-8c2e-1d4e5f6a7b8c",
"kind": "agent",
"handle": "texter",
"display_name": "Texter"
},
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bd",
"kind": "user",
"handle": "sam",
"display_name": "Sam"
}
],
"groups": [],
"spaces": [
{
"id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"name": "Marketing"
}
],
"channels": [
{
"id": "0192f4a0-7b1c-7c33-9e4f-2a3b4c5d6e7f",
"space_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"name": "Intern"
}
]
}
}
listExpiringAccess¶
GET /access/expiring
List the access that expires soon
The list "Expiring soon" of 07 section 9.4: grants that are not revoked and memberships that are not removed (of groups that are not deleted) whose expires_at lies within authz.expiry_reminder_lead from now, and for owners the API tokens of agents and apps that are not revoked and expire within the same lead (never personal tokens, never a token value), ordered by expiry, then kind, then ID. "Extend" is a revocation plus a new grant with a new reason (07 section 2.5), a token is renewed by creating a new one and revoking the old one. Without space_id the instance (owners); with it the space (owner or manage): only grants on the space and its channels and memberships of groups that hold such a grant, no tokens. A space the caller cannot read gives 404, readable without manage 403.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:access.hints.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
space_id |
query | Uuid | no | Only the access within this space; without it the whole instance (owners only). |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ExpiringAccessPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"kind": "membership",
"expires_at": "2026-10-12T09:30:00.000Z",
"membership_id": "0192f4a0-7b1c-7b22-8d3e-4f5a6b7c8d9e",
"group_id": "0192f4a0-7b1c-7e44-9a5b-6c7d8e9f0a1b",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bd"
}
],
"labels": {
"principals": [
{
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bd",
"kind": "user",
"handle": "sam",
"display_name": "Sam"
}
],
"groups": [
{
"id": "0192f4a0-7b1c-7e44-9a5b-6c7d8e9f0a1b",
"name": "Support"
}
],
"spaces": [],
"channels": []
}
}
Admin¶
Instance settings, branding, feature flags, keys, identity providers.
uploadBrandingLogo¶
PUT /instance/branding/logo
Upload the logo
Owner with fresh step-up; nothing of the body is read before authorize allowed the action. Checks in this order (12 3.7): the first part is file (400 validation_failed); the declared type is JPEG, PNG or WebP (415 unsupported_media_type, with reason file_type_denied for a type in file.denied_mime_types); the part holds at most the smaller of file.max_upload_bytes and file.upload_part_bytes (413 payload_too_large) and at least one byte, and no further part follows (400 validation_failed); open sessions (429) and free space of the file system driver (503 unavailable with reason storage_full). The new file is linked at once and replaces the previous logo; it becomes deliverable later, after scan and metadata removal, and until then getBrandingLogo answers 404. Last write wins; no If-Match (06 8).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.branding.updatex-rate-limit-class:rl.admin
Request body (required): multipart/form-data: ImageUpload
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Branding |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 415 | UnsupportedMediaType: Problem codes: unsupported_media_type. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"product_name": "Team Chat",
"accent_color": "loch",
"version": 3
}
deleteBrandingLogo¶
DELETE /instance/branding/logo
Remove the logo
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.branding.updatex-rate-limit-class:rl.admin
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getInstance¶
GET /instance
Instance settings for clients
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: InstanceInfo |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"instance_id": "0192f4a0-7b1c-7db7-89b9-2fe4c48dcb3e",
"branding": {
"product_name": "Team Chat",
"accent_color": "loch",
"version": 3
},
"locale_default": "de",
"spec_version": "1.0.0",
"features": [
{
"key": "dm.enabled",
"enabled": true
}
],
"limits": {
"message_max_content_bytes": 262144,
"message_max_attachments": 10,
"file_max_upload_bytes": 104857600,
"thread_title_max_chars": 200,
"voice_max_duration_ms": 900000
}
}
listInstanceSettings¶
GET /instance/settings
List all instance settings
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.settings.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: InstanceSettingList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"key": "locale.default",
"value": true,
"version": 3,
"updated_at": "2026-10-10T09:30:00.000Z"
}
]
}
putInstanceSetting¶
PUT /instance/settings/{key}
Set an instance setting
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.settings.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
key |
path | string | yes | Pattern ^[a-z0-9_]+(\.[a-z0-9_]+)*$. Example: locale.default. |
If-Match |
header | string | no | Optional ETag; when given, a mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: InstanceSettingPut
Request
{
"value": true
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: InstanceSetting |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"key": "locale.default",
"value": true,
"version": 3,
"updated_at": "2026-10-10T09:30:00.000Z"
}
updateBranding¶
PUT /instance/branding
Change branding
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:instance.branding.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: BrandingUpdate
Request
{
"product_name": "Team Chat",
"accent_color": "loch"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Branding |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"product_name": "Team Chat",
"accent_color": "loch",
"version": 3
}
listFeatureFlags¶
GET /feature-flags
List feature flags
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:feature_flag.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: FeatureFlagList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"key": "voice.enabled",
"kind": "option",
"description": "Voice messages with transcription",
"default": false,
"module": "files",
"orphaned": false,
"enabled": true,
"rollout": {},
"version": 3
}
]
}
putFeatureFlag¶
PUT /feature-flags/{key}
Set a feature flag
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:feature_flag.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
key |
path | string | yes | Pattern ^[a-z0-9_]+(\.[a-z0-9_]+)*$. Example: locale.default. |
If-Match |
header | string | no | Optional ETag; when given, a mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: FeatureFlagPut
Request
{
"enabled": true,
"reason": "Pilot with the support team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: FeatureFlag |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"key": "voice.enabled",
"kind": "option",
"description": "Voice messages with transcription",
"default": false,
"module": "files",
"orphaned": false,
"enabled": true,
"rollout": {},
"version": 3
}
rotateSigningKey¶
POST /signing-keys/rotate
Rotate a server signing key
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:signing_key.rotatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: SigningKeyRotate
Request
{
"purpose": "access_token",
"mode": "scheduled",
"reason": "Scheduled rotation"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SigningKeyRotation |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"purpose": "access_token",
"new_kid": "inv-2026-11",
"previous_kid": "inv-2026-10",
"previous_not_after": "2026-10-10T09:30:00.000Z"
}
listIdentityProviders¶
GET /identity-providers
List identity providers
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity_provider.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: IdentityProviderList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7e26-89e1-d4e246452fb8",
"kind": "oidc",
"name": "Company SSO",
"config": {},
"enabled": true,
"allow_provisioning": false
}
]
}
createIdentityProvider¶
POST /identity-providers
Add an identity provider
Adds an identity provider (08, 2.6). A trusted_header provider that would be enabled (the default) while the public listener is not bound to a loopback address is refused with 409 conflict, reason: trusted_header_requires_loopback and a hint naming server.listen_addr (08, 2.4 rule 1).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity_provider.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: IdentityProviderCreate
Request
{
"kind": "oidc",
"name": "Company SSO",
"config": {}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: IdentityProvider |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7e26-89e1-d4e246452fb8",
"kind": "oidc",
"name": "Company SSO",
"config": {},
"enabled": true,
"allow_provisioning": false
}
getIdentityProvider¶
GET /identity-providers/{provider_id}
Read an identity provider
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity_provider.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
provider_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: IdentityProvider |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7e26-89e1-d4e246452fb8",
"kind": "oidc",
"name": "Company SSO",
"config": {},
"enabled": true,
"allow_provisioning": false
}
deleteIdentityProvider¶
DELETE /identity-providers/{provider_id}
Remove an identity provider
Fails with conflict while identities are linked; disable it instead.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity_provider.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
provider_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateIdentityProvider¶
PATCH /identity-providers/{provider_id}
Change an identity provider
Changes an identity provider; absent members stay. Setting enabled to true on a trusted_header provider while the public listener is not bound to a loopback address is refused with 409 conflict, reason: trusted_header_requires_loopback and a hint naming server.listen_addr (08, 2.4 rule 1). Disabling a provider ends the sessions of its identities (08, 3.3).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:identity_provider.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
provider_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: IdentityProviderUpdate
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: IdentityProvider |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7e26-89e1-d4e246452fb8",
"kind": "oidc",
"name": "Company SSO",
"config": {},
"enabled": true,
"allow_provisioning": false
}
Spaces¶
Spaces and their default operator.
listSpaces¶
GET /spaces
List visible spaces
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SpaceViewList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
]
}
createSpace¶
POST /spaces
Create a space
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: SpaceCreate
Request
{
"name": "Research",
"icon": "flask",
"color": "heather"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Space |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
getSpace¶
GET /spaces/{space_id}
Read a space
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SpaceView |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
updateSpace¶
PATCH /spaces/{space_id}
Change name, icon or color
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: SpaceUpdate
Request
{
"name": "Research"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Space |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
moveSpace¶
POST /spaces/{space_id}/move
Change the global position of a space
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.reorderx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: MovePosition
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Space |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
archiveSpace¶
POST /spaces/{space_id}/archive
Archive a space
Final; there is no unarchive. Every channel of the space becomes read-only for everyone, owners included; reading stays for those who could read before. Archiving is a permission change with access.changed; archived spaces leave listSpaces (07, 4.5).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.archivex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Space |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
setSpaceOperator¶
PUT /spaces/{space_id}/operator
Set the default operator of a space
Optional resolve_i1 runs the guided flow (05 rule 1.6, 10 section 11): the listed agents are authorized with agent.billing_mode.set and switched to organization first, in the same transaction as the change; I1 is checked before the commit, and either both parts commit or none.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:space.operator.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: OperatorSet
Request
{
"mode": "inherit",
"reason": "Support agent takes over"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Space |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"icon": "headset",
"color": "moss",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
Channels¶
Channels, behavior, operator, project binding, tags, templates, direct messages.
listSpaceChannels¶
GET /spaces/{space_id}/channels
List visible channels of a space
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ChannelViewList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
]
}
createChannel¶
POST /spaces/{space_id}/channels
Create a channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ChannelCreate
Request
{
"kind": "text",
"name": "tickets"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
getChannel¶
GET /channels/{channel_id}
Read a channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ChannelView |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
updateChannel¶
PATCH /channels/{channel_id}
Change name or topic
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ChannelUpdate
Request
{
"name": "tickets"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
moveChannel¶
POST /channels/{channel_id}/move
Change the position of a channel in its space
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.reorderx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: MovePosition
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
archiveChannel¶
POST /channels/{channel_id}/archive
Archive a channel
Final; there is no unarchive. The channel becomes read-only for everyone, owners included (403 channel_read_only with reason: channel_archived); reading stays for those who could read before. Archiving is a permission change with access.changed; archived channels leave listSpaceChannels (07, 4.5).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.archivex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
getChannelBehavior¶
GET /channels/{channel_id}/behavior
Read prompt, skills and mention rules
The ETag is settings_version.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.behavior.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ChannelBehavior |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"require_mention": false,
"thread_require_mention": false,
"free_response": false,
"auto_thread": false,
"allow_mentioned_agents": false,
"history_backfill_limit": 20,
"prompt": "Answer support tickets politely. Ask before closing a ticket.",
"skills": [
"support-triage"
],
"settings_version": 1
}
putChannelBehavior¶
PUT /channels/{channel_id}/behavior
Change prompt, skills and mention rules
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.behavior.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ChannelBehaviorPut
Request
{
"require_mention": false,
"thread_require_mention": false,
"free_response": false,
"auto_thread": false,
"allow_mentioned_agents": false,
"history_backfill_limit": 20,
"prompt": "Answer support tickets politely.",
"skills": [
"support-triage"
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ChannelBehavior |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"require_mention": false,
"thread_require_mention": false,
"free_response": false,
"auto_thread": false,
"allow_mentioned_agents": false,
"history_backfill_limit": 20,
"prompt": "Answer support tickets politely. Ask before closing a ticket.",
"skills": [
"support-triage"
],
"settings_version": 1
}
setChannelOperator¶
PUT /channels/{channel_id}/operator
Set or inherit the operator of a channel
Optional resolve_i1 runs the guided flow (05 rule 1.6, 10 section 11): the listed agents are authorized with agent.billing_mode.set and switched to organization first, in the same transaction as the change; I1 is checked before the commit, and either both parts commit or none.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.operator.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: OperatorSet
Request
{
"mode": "inherit",
"reason": "Support agent takes over"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
setChannelReadOnly¶
PUT /channels/{channel_id}/read-only
Switch the read-only state of a channel
Write-protected for every principal including owners; only a running import writes (05, rule 1.8). Switching on cancels active runs in the channel.
The imported channel of a source that is neither completed nor failed is controlled by its ownership list only: 409 conflict with reason import_lead_controls (use setImportLead).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.read_only.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ChannelReadOnlySet
Request
{
"read_only": true,
"reason": "Channel is mirrored from the old system"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": true,
"operator": {
"mode": "inherit"
},
"version": 4,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
putProjectBinding¶
PUT /channels/{channel_id}/project-binding
Bind a forum to a project
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.project.bindx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
If-Match |
header | string | no | Optional ETag; when given, a mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ProjectBindingPut
Request
{
"workspace_ref": "website",
"repository_url": "https://git.example.com/team/website",
"default_branch": "main",
"reason": "Website project moves to this forum"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ProjectBinding |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"workspace_ref": "website",
"repository_url": "https://git.example.com/team/website",
"default_branch": "main",
"runner_config": {},
"ready": false,
"version": 3
}
deleteProjectBinding¶
DELETE /channels/{channel_id}/project-binding
Remove the project binding
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.project.bindx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listForumTags¶
GET /channels/{channel_id}/tags
List forum tags
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ForumTagList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7f24-8f76-a5de0ed16c6f",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "bug",
"color": "rowan",
"sort_key": "a0",
"restricted": false
}
]
}
createForumTag¶
POST /channels/{channel_id}/tags
Create a forum tag
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:forum_tag.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ForumTagCreate
Request
{
"name": "bug",
"color": "rowan"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: ForumTag |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f24-8f76-a5de0ed16c6f",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "bug",
"color": "rowan",
"sort_key": "a0",
"restricted": false
}
deleteForumTag¶
DELETE /channels/{channel_id}/tags/{tag_id}
Delete a forum tag
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:forum_tag.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
tag_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateForumTag¶
PATCH /channels/{channel_id}/tags/{tag_id}
Change a forum tag
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:forum_tag.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
tag_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ForumTagUpdate
Request
{
"name": "bug"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ForumTag |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f24-8f76-a5de0ed16c6f",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "bug",
"color": "rowan",
"sort_key": "a0",
"restricted": false
}
moveForumTag¶
POST /channels/{channel_id}/tags/{tag_id}/move
Change the position of a forum tag
Sets sort_key relative to sibling tags of the same forum; bumps the channel version and writes channel.updated like every tag change (03 forum_tags).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:forum_tag.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
tag_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: MovePosition
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ForumTag |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7f24-8f76-a5de0ed16c6f",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "bug",
"color": "rowan",
"sort_key": "a0",
"restricted": false
}
listTemplates¶
GET /channels/{channel_id}/templates
List own and channel templates
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TemplateList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-777d-8541-d21a5b1c8fe4",
"scope": "personal",
"name": "Escalation",
"content_md": "Please escalate this ticket to second level.",
"version": 3
}
]
}
createChannelTemplate¶
POST /channels/{channel_id}/templates
Create a channel template
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.managex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: TemplateCreate
Request
{
"name": "Escalation",
"content_md": "Please escalate this ticket to second level."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Template |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-777d-8541-d21a5b1c8fe4",
"scope": "personal",
"name": "Escalation",
"content_md": "Please escalate this ticket to second level.",
"version": 3
}
deleteTemplate¶
DELETE /templates/{template_id}
Delete a template
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.managex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
template_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateTemplate¶
PATCH /templates/{template_id}
Change a template
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:template.managex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
template_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: TemplateUpdate
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Template |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-777d-8541-d21a5b1c8fe4",
"scope": "personal",
"name": "Escalation",
"content_md": "Please escalate this ticket to second level.",
"version": 3
}
listMyDms¶
GET /me/dms
List own direct message channels
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:channel.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ChannelViewList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
]
}
createDm¶
POST /dms
Open a direct message channel
Returns the existing channel with 200 when the same participants already have one. 403
feature_disabled when dm.enabled is off.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:dm.createx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: DmCreate
Request
{
"participant_ids": [
"0192f4a0-7b1c-7324-80b6-deddeed437e3"
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Channel |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
leaveDm¶
POST /channels/{channel_id}/leave
Leave a direct message channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:dm.leavex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Threads¶
Threads, titles, done state, moving, tags, agent sessions.
listChannelThreads¶
GET /channels/{channel_id}/threads
List threads or forum posts of a channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
state |
query | ThreadState | no | Filter by state. |
tag_id |
query | Uuid | no | Only threads with this tag. |
sort |
query | ForumSort | no | Sort order, newest first. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ThreadPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
]
}
createThread¶
POST /channels/{channel_id}/threads
Create a forum post or a thread from a message
A first_message uses its client_msg_id for idempotency; without it, send Idempotency-Key. A first_message with kind = voice follows the rules of createMessage (pointers with the prefix /first_message); a voice file whose upload or scan has not ended answers 409 file_not_ready, a blocked or failed file 409 file_blocked, and neither thread nor message is stored.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.createx-rate-limit-class:rl.message
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ThreadCreate
Request
{
"title": "Invoice export fails"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: ThreadCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 200 | Replay: the thread created by an earlier request with the same first_message.client_msg_id or Idempotency-Key. |
application/json: ThreadCreated |
Correlation-Id, RateLimit, RateLimit-Policy, Idempotent-Replay |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
Response
{
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
getThread¶
GET /threads/{thread_id}
Read a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
setThreadTitle¶
PUT /threads/{thread_id}/title
Set the title
Every principal except the thread's operator agent sets title_source = manual. The operator agent may only replace an auto title, which stays auto; on a manual title it gets 409 title_manual.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.title.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ThreadTitlePut
Request
{
"title": "Invoice export fails for March"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
closeThread¶
POST /threads/{thread_id}/close
Mark a thread as done
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.closex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
reopenThread¶
POST /threads/{thread_id}/reopen
Reopen a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.reopenx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
moveThread¶
POST /threads/{thread_id}/move
Move a thread to another channel
Only to channels with the same effective operator; otherwise operator_mismatch.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.movex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ThreadMove
Request
{
"target_channel_id": "0192f4a0-7b1c-77d1-8cf4-a695a7985d2f",
"reason": "Belongs to billing"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-77d1-8cf4-a695a7985d2f",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"moved_at": "2026-10-10T09:30:00.000Z",
"tag_ids": []
}
setThreadTags¶
PUT /threads/{thread_id}/tags
Set forum tags of a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.tags.setx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
If-Match |
header | string | no | Optional ETag; when given, a mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ThreadTagsPut
Request
{
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Thread |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
listAgentSessions¶
GET /threads/{thread_id}/agent-sessions
List current and earlier agent sessions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent_session.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentSessionList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-741b-8617-885056753dc0",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"external_session_ref": "sess-7f3a",
"is_current": true,
"started": true,
"model": "model-large",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
]
}
resetAgentSession¶
POST /threads/{thread_id}/agent-sessions/reset
Start a new agent session in the thread
Ends the current session of the thread with end_reason = reset and returns the ended row; the next run gets session_mode = new (09, 9.2). A run in progress keeps its session. Without a current session 409 conflict with reason no_current_session.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent_session.resetx-rate-limit-class:rl.trigger
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: AgentSession |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-741b-8617-885056753dc0",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"external_session_ref": "sess-7f3a",
"is_current": false,
"started": true,
"model": "model-large",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"created_at": "2026-10-10T09:30:00.000Z",
"ended_at": "2026-10-10T10:05:00.000Z",
"end_reason": "reset",
"version": 3
}
bindAgentSession¶
POST /threads/{thread_id}/agent-sessions/bind
Bind an existing external session
Compare-and-swap over the current session of the thread (09, 9.4); nothing changes on a 409. reason session_changed when expected_current_session_id does not name the current session, session_bound_elsewhere when the reference is current in another thread without take_over. With take_over the permission is checked in that thread too. The next run gets session_mode = bind.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent_session.bindx-rate-limit-class:rl.trigger
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: AgentSessionBind
Request
{
"external_session_ref": "sess-7f3a"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: AgentSession |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-741b-8617-885056753dc0",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"external_session_ref": "sess-7f3a",
"is_current": true,
"started": true,
"model": "model-large",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
Messages¶
Messages, history, edits, reactions, pins.
listPins¶
GET /threads/{thread_id}/pins
List pinned messages
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: PinList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"pinned_by": "0192f4a0-7b1c-72de-8fae-dfbd3e36ff9a",
"pinned_at": "2026-10-10T09:30:00.000Z"
}
]
}
listThreadMessages¶
GET /threads/{thread_id}/messages
Read thread history
At most one of before_seq, after_seq, around_seq. Without any, returns the newest page.
Gaps in thread_seq mean missing data, tombstones fill deleted positions.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:thread.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
before_seq |
query | integer (int64) | no | Messages with thread_seq below this value. |
after_seq |
query | integer (int64) | no | Messages with thread_seq above this value. |
around_seq |
query | integer (int64) | no | Messages centered on this value. |
limit |
query | PageLimit | no | Page size. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: MessagePage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
],
"has_more_before": false,
"has_more_after": false
}
createMessage¶
POST /threads/{thread_id}/messages
Send a message
Idempotent by (author, client_msg_id): a repeat with the same body returns the original with
200 and Idempotent-Replay: true; with a different body 422 idempotency_key_reuse. Sending
into a closed thread reopens it. Agent invocation and follow-ups are evaluated after storing;
denial sets trigger_state = failed with trigger_state_reason. When the message triggers an
agent while one of its attachments is not final (scan or check still running), the agent
invocation waits until all attachments are final or until file.invocation_hold_max has
passed; trigger_state stays received meanwhile. A voice message (kind = voice, 12 8.1)
needs one ready audio attachment: a file whose upload or scan has not ended answers 409 file_not_ready, a blocked or failed file 409 file_blocked, and nothing is stored. A voice
message that triggers an agent without a transcription path gets trigger_state = failed
with voice_unsupported (09, 13); with the server transcript (voice.transcription_mode = service) the invocation waits until the transcript is done or failed, at most
voice.transcript_hold_max.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.createx-rate-limit-class:rl.messagex-idempotency-exempt:client_id
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Request body (required): application/json: MessageCreate
Request
{
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"content_md": "@support-agent the invoice export fails since this morning."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Message |
Correlation-Id, RateLimit, RateLimit-Policy |
| 200 | Replay: the original created by an earlier request with the same client_msg_id. |
application/json: Message |
Correlation-Id, RateLimit, RateLimit-Policy, Idempotent-Replay |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
Response
{
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
getMessage¶
GET /messages/{message_id}
Read a message
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Message |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
deleteMessage¶
DELETE /messages/{message_id}
Delete a message
Idempotent; an already deleted message also gives 204. Moderation of other people's messages
needs manage.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.deletex-rate-limit-class:rl.message
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateMessage¶
PATCH /messages/{message_id}
Edit own message
If-Match carries the expected version. A deleted message gives 410 message_deleted.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.updatex-rate-limit-class:rl.message
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: MessageUpdate
Request
{
"content_md": "@support-agent the invoice export fails since 08:00."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Message |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
listMessageRevisions¶
GET /messages/{message_id}/revisions
Read earlier versions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.revisions.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: MessageRevisionList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"revision": 1,
"content_md": "@support-agent the invoice export fails.",
"edited_by": "0192f4a0-7b1c-72e5-8bdc-9774dd9ce26f",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
listReactions¶
GET /messages/{message_id}/reactions
List who reacted
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:message.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
emoji |
query | string | no | Only this emoji. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ReactionPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"emoji": "👍",
"principal": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
addReaction¶
PUT /messages/{message_id}/reactions/{emoji}
Add own reaction
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:reaction.addx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes | |
emoji |
path | string | yes | Example: %F0%9F%91%8D. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
removeReaction¶
DELETE /messages/{message_id}/reactions/{emoji}
Remove own reaction
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:reaction.removex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes | |
emoji |
path | string | yes | Example: %F0%9F%91%8D. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
pinMessage¶
PUT /messages/{message_id}/pin
Pin a message
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:pin.createx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
unpinMessage¶
DELETE /messages/{message_id}/pin
Unpin a message
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:pin.deletex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
message_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Interactions¶
Buttons, selects and forms on messages.
createInteraction¶
POST /components/{component_id}/interactions
Use a button, select or form
Single-use components accept exactly one interaction; later ones get 409 component_used.
Idempotent by (principal, client_interaction_id).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:interaction.createx-rate-limit-class:rl.interactionx-idempotency-exempt:client_id
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
component_id |
path | Uuid | yes |
Request body (required): application/json: InteractionCreate
Request
{
"client_interaction_id": "0192f4a0-7b1c-704d-8f46-22a420803f92"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Interaction |
Correlation-Id, RateLimit, RateLimit-Policy |
| 200 | Replay: the original created by an earlier request with the same client_interaction_id. |
application/json: Interaction |
Correlation-Id, RateLimit, RateLimit-Policy, Idempotent-Replay |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-77f5-8fe4-151103a7b8b5",
"component_id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"client_interaction_id": "0192f4a0-7b1c-704d-8f46-22a420803f92",
"values": {},
"state": "received",
"created_at": "2026-10-10T09:30:00.000Z"
}
Response
{
"id": "0192f4a0-7b1c-77f5-8fe4-151103a7b8b5",
"component_id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"client_interaction_id": "0192f4a0-7b1c-704d-8f46-22a420803f92",
"values": {},
"state": "received",
"created_at": "2026-10-10T09:30:00.000Z"
}
updateComponent¶
PATCH /components/{component_id}
Disable or change an own component
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:component.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
component_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ComponentUpdate
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Component |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
Files¶
Upload sessions, downloads, thumbnails, transcripts.
createUpload¶
POST /channels/{channel_id}/uploads
Start an upload
Checks in this order (12, 3.1): size against file.max_upload_bytes (413 payload_too_large), quota file.quota_bytes_per_principal (409 conflict with reason quota_exceeded), open sessions (429), free space of the file system driver (503 unavailable with reason storage_full). A denied type answers 415 unsupported_media_type with reason file_type_denied.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.uploadx-rate-limit-class:rl.upload
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: UploadCreate
Request
{
"name": "screenshot.png",
"size_bytes": 48213,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"declared_mime_type": "image/png"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: UploadSession |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 415 | UnsupportedMediaType: Problem codes: unsupported_media_type. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"file_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"mode": "direct",
"part_size_bytes": 1,
"parts": [
{
"part_number": 1,
"url": "/api/v1/uploads/0192f4a0-7b1c-7000-8a00-000000000501/parts/1",
"headers": [
{
"name": "Content-Type",
"value": "application/octet-stream"
}
]
}
],
"expires_at": "2026-10-10T09:30:00.000Z"
}
uploadPart¶
PUT /uploads/{file_id}/parts/{part_number}
Upload one part in direct mode
Parts can be sent in parallel and in any order (12, 3.2). The same part number with the same Content-Digest answers 200 without new work; with another digest 409 conflict with reason part_conflict. Wrong length or digest: 400 validation_failed with errors[].code part_digest_mismatch, nothing is stored. An expired session answers 410 gone.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.uploadx-rate-limit-class:rl.upload
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
part_number |
path | integer | yes | Minimum 1. |
Content-Digest |
header | string | yes | RFC 9530 digest of the part with the member sha-256, e.g. sha-256=:<base64>:; other members are ignored. |
Request body (required): application/octet-stream: string (binary)
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UploadPartResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"part_number": 1,
"etag": "\"3858f62230ac3c915f300c664312c11f\""
}
completeUpload¶
POST /uploads/{file_id}/complete
Finish an upload
Closes the session and queues the job files.scan, which checks size and SHA-256, detects the MIME type and runs the malware scan. The file is
downloadable after scan_status is clean or skipped. parts is checked against the confirmed parts: a duplicate or out-of-range number gives 400, another etag 409 conflict with reason part_conflict. A completed session answers 200 with the file again. Missing parts answer 409 conflict with reason upload_incomplete; an expired session answers 410 gone (12, 3.4 and 3.6).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.uploadx-rate-limit-class:rl.upload
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: UploadComplete
Request
{
"parts": [
{
"part_number": 1,
"etag": "\"3858f62230ac3c915f300c664312c11f\""
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: File |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
getUpload¶
GET /uploads/{file_id}
Read the state of an own upload
Confirmed parts of an own upload, so a client can resume after a network loss (12, 3.2). upload_state is pending for an open session without a confirmed part, uploading with at least one, complete once completed. An aborted or expired session answers 410 gone.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.uploadx-rate-limit-class:rl.upload
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UploadState |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"file_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"upload_state": "uploading",
"part_size_bytes": 8388608,
"completed_parts": [
{
"part_number": 1,
"etag": "\"9b2cf535f27731c974343645a3985328\""
}
],
"expires_at": "2026-10-10T09:30:00.000Z"
}
abortUpload¶
DELETE /uploads/{file_id}
Abort an upload
Ends an open own session: its parts are deleted, the file becomes upload_state failed and file.updated goes to the uploader. An aborted or expired session answers 204 again; a completed one 409 invalid_state_transition.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.deletex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getFile¶
GET /files/{file_id}
Read file metadata
The header ETag is the version of the transcript of the file, derived from its status, source, language and text (03 R-DM-48, 12 8.2); getTranscript sends the same value, and submitTranscript expects it in If-Match.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: File |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
deleteFile¶
DELETE /files/{file_id}
Delete an unattached file
Deletes an own file that is not attached. A file the caller already deleted answers 204 as well; an unknown, foreign or purged file answers 404 not_found. An attached file answers 409 conflict with reason file_attached (delete the message instead); an avatar, logo or export file answers 409 conflict with reason purpose_not_deletable. The objects and the row of the file are removed within privacy.object_delete_delay.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.deletex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
downloadFile¶
GET /files/{file_id}/content
Download a file
Answers 200 with the bytes (supports Range); there are no presigned GET URLs (ADR 0048).
Media players without DPoP use a ticket (createFileTicket) in the query parameter ticket
instead of Authorization. 409 file_not_ready while the scan is pending, 409 file_blocked
for blocked or failed files; without read access always 404 (12, 9.3). Exactly one byte range
gives 206, several ranges are ignored (200 with the whole file), a range outside the file
gives 416. Types outside the inline list of 12 9.3 (HTML, SVG, PDF and every other type) are sent as
application/octet-stream with Content-Disposition: attachment, nosniff and the sandbox
CSP. An Authorization header wins over a ticket parameter. Pass-through via the server
only (ADR 0048).
- Security: dpopAuth or bearerAuth or fileTicket
x-authz-action:file.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
ticket |
query | string | no | Fetch ticket of createFileTicket (security scheme fileTicket, 12 9.2). Accepted only by downloadFile and downloadThumbnail; ignored when the request carries Authorization. A bearer secret: never logged. |
Range |
header | string | no | One byte range (RFC 9110 section 14), for example bytes=0-1023, bytes=1024- or bytes=-500. Exactly one range gives 206; several ranges and invalid values are ignored (200); a range that starts at or after the end gives 416 (12, 9.3). |
If-Range |
header | string | no | Applies Range only when equal to the current strong ETag; any other value, an HTTP date included, gives the whole variant (200). |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | The whole file (12, 9.3; ADR 0048). | application/octet-stream: string (binary)image/jpeg: string (binary)image/png: string (binary)image/gif: string (binary)audio/mp4: string (binary)audio/mpeg: string (binary)video/mp4: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy, Content-Disposition, Content-Security-Policy, Cross-Origin-Resource-Policy, Cache-Control, ETag, Repr-Digest, Accept-Ranges |
| 206 | Exactly one byte range of the file (12, 9.3; ADR 0048). | application/octet-stream: string (binary)image/jpeg: string (binary)image/png: string (binary)image/gif: string (binary)audio/mp4: string (binary)audio/mpeg: string (binary)video/mp4: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy, Content-Disposition, Content-Security-Policy, Cross-Origin-Resource-Policy, Cache-Control, ETag, Repr-Digest, Accept-Ranges, Content-Range |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | FileConflict: Problem codes: file_not_ready, file_blocked. |
application/problem+json: Problem |
Correlation-Id, Retry-After |
| 416 | RangeNotSatisfiable: Problem codes: range_not_satisfiable. |
application/problem+json: Problem |
Correlation-Id, Content-Range |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
downloadThumbnail¶
GET /files/{file_id}/thumbnails/{variant}
Download a thumbnail
Accepts a fetch ticket in the query parameter ticket like downloadFile (push preview
image_url, ADR 0048). 409 file_not_ready or file_blocked as for downloadFile; a variant
the file does not have gives 404. Thumbnails are always inline with their own type; range,
headers and caching as for downloadFile (12, 9.3).
- Security: dpopAuth or bearerAuth or fileTicket
x-authz-action:file.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
variant |
path | string | yes | Values: small, medium, large, poster. |
ticket |
query | string | no | Fetch ticket of createFileTicket (security scheme fileTicket, 12 9.2). Accepted only by downloadFile and downloadThumbnail; ignored when the request carries Authorization. A bearer secret: never logged. |
Range |
header | string | no | One byte range (RFC 9110 section 14), for example bytes=0-1023, bytes=1024- or bytes=-500. Exactly one range gives 206; several ranges and invalid values are ignored (200); a range that starts at or after the end gives 416 (12, 9.3). |
If-Range |
header | string | no | Applies Range only when equal to the current strong ETag; any other value, an HTTP date included, gives the whole variant (200). |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | The whole thumbnail (12, 9.3; ADR 0048). | image/jpeg: string (binary)image/png: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy, Content-Disposition, Content-Security-Policy, Cross-Origin-Resource-Policy, Cache-Control, ETag, Repr-Digest, Accept-Ranges |
| 206 | Exactly one byte range of the thumbnail (12, 9.3; ADR 0048). | image/jpeg: string (binary)image/png: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy, Content-Disposition, Content-Security-Policy, Cross-Origin-Resource-Policy, Cache-Control, ETag, Repr-Digest, Accept-Ranges, Content-Range |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | FileConflict: Problem codes: file_not_ready, file_blocked. |
application/problem+json: Problem |
Correlation-Id, Retry-After |
| 416 | RangeNotSatisfiable: Problem codes: range_not_satisfiable. |
application/problem+json: Problem |
Correlation-Id, Content-Range |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
createFileTicket¶
POST /files/{file_id}/tickets
Create a short-lived fetch ticket
For media players and "open with" that cannot send a DPoP proof. Every fetch with the ticket
checks signature, expiry, session and file.read again (12, 9.2). A ticket binds to the login
session of the caller: a principal without a session (agent, app, API token) gets 403
forbidden with reason step_up_not_possible. No ticket is issued for a file that is not
deliverable (409 file_not_ready or file_blocked), and a variant the file does not have
gives 404. A repeated call mints a new ticket.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.readx-rate-limit-class:rl.readx-idempotency-exempt:read_only
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Request body (required): application/json: FileTicketCreate
Request
{
"variant": "original"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: FileTicket |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | FileConflict: Problem codes: file_not_ready, file_blocked. |
application/problem+json: Problem |
Correlation-Id, Retry-After |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"url": "/api/v1/files/0192f4a0-7b1c-75c7-88f6-199cc394b56a/content?ticket=c2lnbmVk",
"expires_at": "2026-10-10T09:30:00.000Z"
}
getTranscript¶
GET /files/{file_id}/transcript
Read the transcript of a voice message
409 file_not_ready or file_blocked as for downloadFile; without read access always 404 (12, 9.3). Normal authentication only, never a fetch ticket. text, language and source are present only with status done. The header ETag is the derived version of the transcript, the same value as in getFile and the If-Match of submitTranscript.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Transcript |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | FileConflict: Problem codes: file_not_ready, file_blocked. |
application/problem+json: Problem |
Correlation-Id, Retry-After |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"file_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"status": "done",
"text": "Please call the customer back tomorrow morning.",
"language": "en",
"source": "agent"
}
requestTranscription¶
POST /files/{file_id}/transcribe
Request a transcript
403 feature_disabled when voice.enabled is off. Starts the server transcript in mode service of voice.transcription_mode (12, 8.2). An unknown or invisible file answers 404; another mode, or a file that is not a voice format, gives 409 conflict with reason transcription_unavailable; a file that is not ready gives 409 file_not_ready or file_blocked. A transcript in status none or failed goes to pending and a new job starts; in status pending or done nothing changes. The answer is the current Transcript; the result arrives through file.updated.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.transcribex-rate-limit-class:rl.upload
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted; processing continues asynchronously. | application/json: Transcript |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"file_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"status": "pending"
}
Search¶
Full-text search filtered by permissions.
search¶
GET /search
Full-text search
Results are filtered by message.read, thread.read and file.read inside the query; counts
are not returned. Page size search.page_size_default, at most search.page_size_max (14, 4.7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:search.queryx-rate-limit-class:rl.search
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
q |
query | string | yes | Query in web search syntax: words, "phrases", or, -word. Min length 1. |
type |
query | string | no | Result type; default messages (14, 11). Values: messages, threads, files. Default: messages. |
sort |
query | string | no | Order of the hits (14, 4.5). Values: relevance, newest. Default: relevance. |
space_id |
query | array of Uuid | no | Only channels of these spaces, intersected with the visible ones. |
channel_id |
query | array of Uuid | no | Only these channels, intersected with the visible ones. |
thread_id |
query | Uuid | no | Restrict to a thread. |
author_id |
query | Uuid | no | Author of the message or uploader of the file. |
agent_id |
query | Uuid | no | Threads operated by this agent. |
after |
query | Timestamp | no | Created at or after. |
before |
query | Timestamp | no | Created before. |
has_file |
query | boolean | no | Only messages with at least one attachment. |
thread_state |
query | ThreadState | no | Only open or closed threads. |
tag_id |
query | array of Uuid | no | Forum tags of the thread. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SearchHitPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"kind": "message",
"score": 1.5,
"thread_title": "Invoice export fails",
"channel_name": "tickets",
"space_name": "Support",
"segments": [
{
"text": "the ",
"match": false
},
{
"text": "invoice",
"match": true
},
{
"text": " export fails",
"match": false
}
]
}
],
"candidates_capped": false
}
searchThreadTitles¶
GET /search/thread-titles
Prefix search over thread titles
For the quick switcher (14, 4.9): words shorter than search.prefix_min_chars are dropped; same access filter as /search, newest activity first. Page size search.page_size_default, at most search.page_size_max.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:search.queryx-rate-limit-class:rl.search
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit |
query | PageLimit | no | |
q |
query | string | yes | Typed prefix text. Min length 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ThreadTitleHitList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"title": "Invoice export fails",
"last_activity_at": "2026-10-10T09:30:00.000Z"
}
]
}
Sync¶
Snapshot and catch-up over REST.
getSnapshot¶
GET /sync/snapshot
Load a snapshot
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:sync.snapshot.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Snapshot |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"head_seq": 5300,
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"permission_version": 418,
"principal": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"is_owner": false,
"spaces": [
{
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
],
"channels": [
{
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
},
"level": "read",
"capabilities": [
"approve_actions"
]
}
],
"sidebar": [
{
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"collapsed": false,
"sort_key": "a0V",
"version": 3
}
],
"unread_threads": [
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"unread_count": 1,
"mention_count": 1,
"last_message_seq": 5301,
"last_read_seq": 5301
}
],
"active_runs": [
{
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"state_reason": "user_cancelled",
"version": 3,
"billing_mode_expected": "personal",
"status_line": "Reading the export logs",
"summary": "Found the cause and proposed a fix",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"step_count": 1,
"queued_at": "2026-10-10T09:30:00.000Z"
}
],
"agents": [
{
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"state": "unknown"
}
],
"settings": [
{
"key": "composer.enter_sends",
"value": true,
"version": 3
}
],
"drafts": [
{
"id": "0192f4a0-7b1c-7f2d-8106-461e390824dc",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"version": 3
}
],
"features": [
{
"key": "dm.enabled",
"enabled": false
}
]
}
listEvents¶
GET /events
Catch up on events after a sequence
Same filtering as the gateway. 410 resync_required with reason when catch-up is impossible.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:events.catch_upx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
after |
query | integer (int64) | yes | Last processed seq. Minimum 0. |
epoch |
query | Uuid | no | Sync epoch stored with the cursor (04 section 7.5). A different epoch answers 410 resync_required with reason = epoch_changed. Absent only before the first catch-up; then cursor_ahead is the second net (R-SY-04). |
limit |
query | integer | no | At most sync.catchup_page_size. Minimum 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: EventPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"events": [
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"scope": {},
"resource": {
"kind": "message"
},
"type": "message.created",
"payload": {
"message": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
],
"next_cursor": 1,
"head_seq": 5301,
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60"
}
Preferences¶
Read state, drafts, settings, sidebar, notifications, quiet hours.
getMySidebar¶
GET /me/sidebar
Read own sidebar state
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SidebarStateList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"collapsed": false,
"sort_key": "a0V",
"version": 3
}
]
}
putMySidebarSpace¶
PUT /me/sidebar/spaces/{space_id}
Collapse or reorder a space for oneself
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:sidebar.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
path | Uuid | yes |
Request body (required): application/json: SidebarStatePut
Request
{
"collapsed": false
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: SidebarState |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"collapsed": false,
"sort_key": "a0V",
"version": 3
}
putReadState¶
PUT /threads/{thread_id}/read-state
Advance the read position
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:read_state.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Request body (required): application/json: ReadStatePut
Request
{
"last_read_seq": 42
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ReadState |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"last_read_seq": 41,
"mention_count": 1,
"version": 3
}
markThreadUnread¶
POST /threads/{thread_id}/read-state/mark-unread
Move the read position back
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:read_state.mark_unreadx-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ReadStatePut
Request
{
"last_read_seq": 42
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ReadState |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"last_read_seq": 41,
"mention_count": 1,
"version": 3
}
putThreadDraft¶
PUT /threads/{thread_id}/draft
Save the draft of a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:draft.writex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Request body (required): application/json: DraftPut
Request
{
"content_md": "Draft of a reply"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: DraftPutResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"draft": {
"id": "0192f4a0-7b1c-7ad4-8297-1c4f06dd683c",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"content_md": "Draft of a reply",
"file_ids": [
"0192f4a0-7b1c-746e-8bc6-de981880ca4c"
],
"version": 3
},
"overwrote_newer": false
}
deleteThreadDraft¶
DELETE /threads/{thread_id}/draft
Delete the draft of a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:draft.writex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
putChannelDraft¶
PUT /channels/{channel_id}/draft
Save the draft of a new forum post
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:draft.writex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Request body (required): application/json: DraftPut
Request
{
"content_md": "Draft of a reply"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: DraftPutResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"draft": {
"id": "0192f4a0-7b1c-7ad4-8297-1c4f06dd683c",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"content_md": "Draft of a reply",
"file_ids": [
"0192f4a0-7b1c-746e-8bc6-de981880ca4c"
],
"version": 3
},
"overwrote_newer": false
}
deleteChannelDraft¶
DELETE /channels/{channel_id}/draft
Delete the draft of a new forum post
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:draft.writex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listMyReadStates¶
GET /me/read-states
List own read positions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
query | Uuid | yes | Only threads of this channel. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ReadStateList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"last_read_seq": 41,
"mention_count": 1,
"version": 3
}
]
}
listMyDrafts¶
GET /me/drafts
List own drafts
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:draft.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: DraftList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7ad4-8297-1c4f06dd683c",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"content_md": "Draft of a reply",
"file_ids": [
"0192f4a0-7b1c-746e-8bc6-de981880ca4c"
],
"version": 3
}
]
}
listMySettings¶
GET /me/settings
List own settings
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UserSettingList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"key": "composer.enter_sends",
"value": true,
"version": 3
}
]
}
putMySetting¶
PUT /me/settings/{key}
Set an own setting
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
key |
path | string | yes | Pattern ^[a-z0-9_]+(\.[a-z0-9_]+)*$. Example: locale.default. |
Request body (required): application/json: UserSettingPut
Request
{
"value": true
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UserSetting |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"key": "composer.enter_sends",
"value": true,
"version": 3
}
deleteMySetting¶
DELETE /me/settings/{key}
Reset an own setting to default
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
key |
path | string | yes | Pattern ^[a-z0-9_]+(\.[a-z0-9_]+)*$. Example: locale.default. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listMyNotificationPreferences¶
GET /me/notification-preferences
List notification levels
The caller's own levels, ordered by target kind, then target id. Only targets the caller can still read are listed; rows on targets the caller lost stay stored and appear again when the right returns.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: NotificationPreferenceList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"target_kind": "space",
"target_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"level": "all",
"version": 3
}
]
}
putNotificationPreference¶
PUT /me/notification-preferences/{target_kind}/{target_id}
Set the notification level of a target
Sets the caller's level on a space, channel or thread the caller can read, the main thread of a text channel included. An unknown target, an id of another kind and a target without read right give the same 404. An archived target (or a channel in an archived space) takes no new preference: 409 conflict with reason target_archived. muted_until is stored as given (whole microseconds), also when it has passed; a passed value has no effect. A write that changes nothing answers 200 without event and without a new version.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:notification_pref.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
target_kind |
path | string | yes | Values: space, channel, thread. |
target_id |
path | Uuid | yes |
Request body (required): application/json: NotificationPreferencePut
Request
{
"level": "all"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: NotificationPreference |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"target_kind": "space",
"target_id": "0192f4a0-7b1c-7fd5-831e-d4370e087874",
"level": "all",
"version": 3
}
deleteNotificationPreference¶
DELETE /me/notification-preferences/{target_kind}/{target_id}
Inherit the notification level again
Removes the caller's level on the target, so it inherits again. Answers 204 also when no row is stored (then without event); deleting stays possible on an archived target. A later put starts again at version 1.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:notification_pref.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
target_kind |
path | string | yes | Values: space, channel, thread. |
target_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listMyQuietHours¶
GET /me/quiet-hours
List quiet hours
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:settings.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: QuietHoursList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7c3e-88ef-5d4efd8f4f24",
"weekdays": 31,
"start_local": "22:00",
"end_local": "07:00",
"time_zone": "Europe/Berlin",
"enabled": true,
"version": 3
}
]
}
createQuietHoursRule¶
POST /me/quiet-hours
Add a quiet hours rule
Adds a rule. time_zone must be an IANA zone name (400 validation_failed with errors[].code unknown_time_zone); absent means the person's time zone. Every write sends the complete list in quiet_hours.updated; a write that would make that list larger than sync.event_payload_max_bytes is refused with 400 validation_failed and errors[].code limit_reached.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:quiet_hours.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: QuietHoursRuleInput
Request
{
"weekdays": 31,
"start_local": "22:00",
"end_local": "07:00",
"time_zone": "Europe/Berlin",
"enabled": true
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: QuietHoursRule |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7c3e-88ef-5d4efd8f4f24",
"weekdays": 31,
"start_local": "22:00",
"end_local": "07:00",
"time_zone": "Europe/Berlin",
"enabled": true,
"version": 3
}
putQuietHoursRule¶
PUT /me/quiet-hours/{rule_id}
Change a quiet hours rule
Replaces the whole rule; an absent time_zone clears it (the rule then follows the person's time zone). Equal values answer 200 without event and without a new version. time_zone and the list size are checked as for createQuietHoursRule (unknown_time_zone, limit_reached).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:quiet_hours.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
rule_id |
path | Uuid | yes |
Request body (required): application/json: QuietHoursRuleInput
Request
{
"weekdays": 31,
"start_local": "22:00",
"end_local": "07:00",
"time_zone": "Europe/Berlin",
"enabled": true
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: QuietHoursRule |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7c3e-88ef-5d4efd8f4f24",
"weekdays": 31,
"start_local": "22:00",
"end_local": "07:00",
"time_zone": "Europe/Berlin",
"enabled": true,
"version": 3
}
deleteQuietHoursRule¶
DELETE /me/quiet-hours/{rule_id}
Delete a quiet hours rule
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:quiet_hours.updatex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
rule_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Agents¶
Agent administration and backend policy.
setAllAgentsBillingMode¶
PUT /instance/agent-billing-mode
Switch the backend policy of all agents
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.billing_mode.set_allx-rate-limit-class:rl.admin
Request body (required): application/json: BillingModeSetAll
Request
{
"billing_mode": "organization",
"reason": "Switch all agents to the company key"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: BillingModeSetAllResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"changed_agent_ids": [
"0192f4a0-7b1c-7d65-8e06-d83d1842d15e"
]
}
listAgents¶
GET /agents
List visible agents
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown"
},
"operator_config": {},
"version": 3
}
]
}
createAgent¶
POST /agents
Create an agent
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: AgentCreate
Request
{
"handle": "support-agent",
"display_name": "Support Agent",
"adapter_kind": "hermes",
"description": "Answers support tickets"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
getAgent¶
GET /agents/{agent_id}
Read an agent with reported state
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
updateAgent¶
PATCH /agents/{agent_id}
Change an agent
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: AgentUpdate
Request
{
"display_name": "Support Agent"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
disableAgent¶
POST /agents/{agent_id}/disable
Disable an agent
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.disablex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
enableAgent¶
POST /agents/{agent_id}/enable
Enable an agent
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.enablex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
setAgentBillingMode¶
PUT /agents/{agent_id}/billing-mode
Switch the backend policy of an agent
Switching to personal requires credential_holder_id and fails with i1_violation if anyone
else could trigger the agent.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.billing_mode.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: BillingModeSet
Request
{
"billing_mode": "personal",
"reason": "Team uses the agent now"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
setCredentialHolder¶
PUT /agents/{agent_id}/credential-holder
Change the credential holder
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.credential_holder.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: CredentialHolderSet
Request
{
"credential_holder_id": "0192f4a0-7b1c-7ae9-8d74-7494cd730bc3",
"reason": "Handover to deputy"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown",
"runtime_version": "2.3.1"
},
"operator_config": {},
"version": 3
}
setAgentToolClass¶
PUT /agents/{agent_id}/tool-class
Set the tool class of an agent
Target tool class (chat < scoped < host, 07 2.11). authorize uses the higher of target and reported class; a guest run needs a matching tool class (SR2).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.tool_class.setx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: ToolClassSet
Request
{
"tool_class": "scoped",
"reason": "Agent now works in a project checkout"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Agent |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "scoped",
"description": "Answers support tickets",
"billing_mode": "organization",
"presence": {
"state": "unknown"
},
"operator_config": {},
"version": 4
}
Agent runtime¶
Endpoints for agent adapters: heartbeat, consumer, config, run lifecycle.
reportAgentSession¶
POST /threads/{thread_id}/agent-sessions/report
Report the external session reference and model
The adapter reports the session of its own active run in the thread (09, 9.1 and 9.5). If-Match is the compare-and-swap over agent_sessions.version: absent means the run has no session row yet, and the report creates it; a row that exists needs its version, otherwise 412 version_conflict with current. 409 conflict with reason session_bound_elsewhere (the reference is current in another thread), session_changed (the thread got another current session) or session_not_bound (bind_failed without a started session row).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent_session.reportx-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | no | Optional ETag; when given, a mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: AgentSessionReport
Request
{
"external_session_ref": "sess-7f3a",
"model": "model-large"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentSession |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-741b-8617-885056753dc0",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"external_session_ref": "sess-7f3a",
"is_current": true,
"started": true,
"model": "model-large",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
respondToInteraction¶
POST /interactions/{interaction_id}/respond
Acknowledge or answer an interaction
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:interaction.respondx-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
interaction_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: InteractionRespond
Request
{
"state": "acknowledged"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Interaction |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-77f5-8fe4-151103a7b8b5",
"component_id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"client_interaction_id": "0192f4a0-7b1c-704d-8f46-22a420803f92",
"values": {},
"state": "received",
"created_at": "2026-10-10T09:30:00.000Z"
}
submitTranscript¶
PUT /files/{file_id}/transcript
Store a transcript created by the agent
Mode agent of voice.transcription_mode only (12, 8.2). Only the operator agent of the thread whose message the voice file is attached to, with read access, may store the transcript; a file the caller cannot read, an unattached file of another uploader and an unknown id answer the same 404, and a visible caller who is not that operator gets 403 forbidden. Another mode, or a file that is not a voice format, gives 409 conflict with reason transcription_unavailable; a file that is not ready gives 409 file_not_ready or file_blocked. If-Match carries the transcript ETag of getFile or getTranscript (derived from status, source, language and text, 03 R-DM-48); without it or with * 428 precondition_required, with another value 412 version_conflict with the current Transcript in current and its ETag. text may be empty, must not contain U+0000 (invalid) and is at most message.max_content_bytes UTF-8 bytes (too_long). The answer has status done and source agent and the new ETag; a later submit with that value replaces the transcript. No audit entry.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:file.transcript.submitx-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
file_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: TranscriptSubmit
Request
{
"text": "Please call the customer back tomorrow morning.",
"language": "en"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Transcript |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"file_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"status": "done",
"text": "Please call the customer back tomorrow morning.",
"language": "en",
"source": "agent"
}
sendHeartbeat¶
POST /agents/me/heartbeat
Report state and actual billing mode
The adapter reports the whole state of its runtime (agent_heartbeat.v1, 09 section 4.8); the member agent of the gateway op heartbeat has the same effect. Only an agent may call it (agent-self); the body carries no agent id. The last heartbeat wins: an absent optional member means "not reported", except project_readiness, which is applied only when present and changed since the last list this server process applied (ApplyProjectReadiness of M2-03, in its own transaction).
The server validates every member and the closed keys of details itself, also the patterns of names, versions and codes; a violation answers 400 validation_failed with every field error; rate_limit carries only state and an optional resets_at (M6-14). A change of reported_billing_mode or reported_tool_class, also from or to "not reported", is stored at once and audited with action agent.heartbeat; the other fields are stored at most once per agent.heartbeat_persist_interval. The presence becomes offline once agent.presence_timeout passes without a heartbeat. The server compares the reported with the configured mode at each heartbeat and returns the warnings of AgentRuntimeStatus.warnings; the reported mode is evidence for display, warning, audit and alarm and never a permission (BR-05). interval_ms is sync.heartbeat_interval.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.heartbeatx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Request body (required): application/json: Heartbeat
Request
{
"state": "online",
"runtime_version": "2.3.1",
"reported_billing_mode": "personal"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: HeartbeatAck |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"presence": {
"state": "online",
"reported_billing_mode": "personal",
"runtime_version": "2.3.1",
"last_heartbeat_at": "2026-10-20T09:00:00.000Z",
"billing_mode_matches": true
},
"interval_ms": 30000
}
getConsumerState¶
GET /agents/me/consumers/{consumer}
Read the cursor of a consumer
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.events.consumex-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
consumer |
path | string | yes | Pattern ^[a-z0-9][a-z0-9_-]*$. Example: default. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ConsumerState |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"consumer": "default",
"acked_seq": 5301,
"head_seq": 5301
}
pollAgentEvents¶
GET /agents/me/consumers/{consumer}/events
Fetch events for a consumer without WebSocket
Delivers from acked_seq + 1. Invocation events carry a fresh invocation_token.
Unacknowledged events are delivered again after agent.ack_timeout.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.events.consumex-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
consumer |
path | string | yes | Pattern ^[a-z0-9][a-z0-9_-]*$. Example: default. |
limit |
query | integer | no | At most agent.max_inflight_events. Minimum 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: EventPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"events": [
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"scope": {},
"resource": {
"kind": "message"
},
"type": "message.created",
"payload": {
"message": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
],
"next_cursor": 1,
"head_seq": 5301,
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60"
}
ackAgentEvents¶
POST /agents/me/consumers/{consumer}/ack
Acknowledge events up to a sequence
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.events.consumex-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
consumer |
path | string | yes | Pattern ^[a-z0-9][a-z0-9_-]*$. Example: default. |
Request body (required): application/json: ConsumerAck
Request
{
"seq": 5301
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ConsumerState |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"consumer": "default",
"acked_seq": 5301,
"head_seq": 5301
}
listServedChannels¶
GET /agents/me/channels
List channels the agent serves
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.config.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentChannelConfigList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"behavior": {
"require_mention": false,
"thread_require_mention": false,
"free_response": false,
"auto_thread": false,
"allow_mentioned_agents": false,
"history_backfill_limit": 20,
"prompt": "Answer support tickets politely. Ask before closing a ticket.",
"skills": [
"support-triage"
],
"settings_version": 1
}
}
]
}
getServedChannelConfig¶
GET /agents/me/channels/{channel_id}/config
Read prompt, skills and project binding of a served channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.config.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentChannelConfig |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"behavior": {
"require_mention": false,
"thread_require_mention": false,
"free_response": false,
"auto_thread": false,
"allow_mentioned_agents": false,
"history_backfill_limit": 20,
"prompt": "Answer support tickets politely. Ask before closing a ticket.",
"skills": [
"support-triage"
],
"settings_version": 1
}
}
getAgentTriggerers¶
GET /agents/me/triggerers
List who may trigger this agent
Principals with effective trigger on a channel the agent operates, with permission_version. The adapter keeps it as allow list and reloads on access.changed (09, 15).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:agent.triggerers.readx-rate-limit-class:rl.agent_runtime
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AgentTriggerers |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"principal_ids": [
"0192f4a0-7b1c-7f89-8d6b-6960453241bc"
],
"permission_version": 418
}
patchRun¶
PATCH /runs/{run_id}
Apply a live-box patch
Same as gateway op run.update (one use case). Only the run's own agent patches, only while
the run is queued, running or waiting_input. A path or op outside the allowed set of
09 section 5.3 (for example /state) gives 400 validation_failed with errors[].code
patch_path_forbidden and the pointer of the op. An ended run gives 409 conflict with
reason run_not_active, checked before the version. A wrong base_version gives 409
base_version_conflict with the current document in current, exactly as getRun
answers it. Set semantics: add and replace set a member also when it is absent,
remove of an absent member is a no-op, and one stored patch raises the version by one.
A follow-up state moves forward only (queued to delivered or absorbed, delivered to
absorbed); a backward change gives 409 invalid_state_transition.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.updatex-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: RunPatch
Request
{
"base_version": 7,
"ops": [
{
"op": "replace",
"path": "/steps/0192f4a0-7b1c-7000-8a00-0000000000a1/status",
"value": "completed"
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: RunPatchResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"version": 8
}
startRun¶
POST /runs/{run_id}/start
Start a queued run
Compare-and-swap queued -> running after checking the invocation token. Repeating the call
with the same token after success returns 200 with Idempotent-Replay: true while the run is
running; any other token gets 409 already_started. Once the run waits for input, the start
token is consumed and gets 403 invocation_token_invalid with reason: superseded. A different billing_mode_used fails the run with
billing_mode_mismatch; a tool_class_used above the tool_class of the token fails it with
409 tool_class_mismatch. A token error gives 403 invocation_token_invalid with reason
expired (renew with renewInvocationToken, then start again), superseded (a newer
delivery replaced it) or invalid (09 section 4.5).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.startx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: RunStart
Request
{
"invocation_token": "eyJhbGciOiJFZERTQSIsImtpZCI6Imludi0yMDI2LTEwIn0.e30.sig",
"billing_mode_used": "personal",
"tool_class_used": "scoped",
"external_session_ref": "sess-7f3a",
"model": "model-large"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. A repeated start with the same token while the run is running answers the current run with Idempotent-Replay: true and changes nothing (06 section 7 point 5). |
application/json: Run |
Correlation-Id, Idempotent-Replay, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "running",
"version": 3,
"billing_mode_expected": "personal",
"model": "model-large",
"status_line": "Reading the export logs",
"metrics": {
"context_pct": 37.5
},
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"steps": {
"0192f4a0-7b1c-7986-8350-06ee441b527a": {
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
},
"followups": {
"0192f4a0-7b1c-77d2-8ef5-9f8e2e1db96b": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "queued"
}
},
"queued_at": "2026-10-10T09:30:00.000Z"
}
resumeRun¶
POST /runs/{run_id}/resume
Resume a run that waited for input
waiting_input -> running with the token of the interaction or follow-up delivery. The consumed start token (its jti equals runs.started_jti) gets 403 invocation_token_invalid with reason: superseded (09 section 4.5).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.startx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: RunStart
Request
{
"invocation_token": "eyJhbGciOiJFZERTQSIsImtpZCI6Imludi0yMDI2LTEwIn0.e30.sig",
"billing_mode_used": "personal",
"tool_class_used": "scoped",
"external_session_ref": "sess-7f3a",
"model": "model-large"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. A repeated start with the same token while the run is running answers the current run with Idempotent-Replay: true and changes nothing (06 section 7 point 5). |
application/json: Run |
Correlation-Id, Idempotent-Replay, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "running",
"version": 3,
"billing_mode_expected": "personal",
"model": "model-large",
"status_line": "Reading the export logs",
"metrics": {
"context_pct": 37.5
},
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"steps": {
"0192f4a0-7b1c-7986-8350-06ee441b527a": {
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
},
"followups": {
"0192f4a0-7b1c-77d2-8ef5-9f8e2e1db96b": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "queued"
}
},
"queued_at": "2026-10-10T09:30:00.000Z"
}
renewInvocationToken¶
POST /runs/{run_id}/invocation-token
Get a fresh invocation token for an own waiting run
For a run in queued or waiting_input whose invocation token expired before the start
(09 section 4.5.1). The body carries the current token; its expiry is not checked, but its
signature, audience, run and jti are: the jti equals the current one (runs.invocation_jti)
or the one the last renewal replaced (runs.renewed_from_jti, retry after a lost answer), and
it is not consumed by a start (runs.started_jti is NULL or differs, SQL started_jti IS DISTINCT FROM jti). A retry with the replaced token issues a
fresh token again; the run still starts at most once. The server repeats every check it runs
before a delivery (agent.invoke for the triggering person with current permissions, I2, SR2,
SR3); on failure the run becomes failed and the answer is 403 agent_invocation_denied. A
replaced or consumed token gets 403 invocation_token_invalid with reason: superseded; a
run that already started gets 409 already_started.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.token.renewx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: InvocationTokenRenew
Request
{
"invocation_token": "eyJhbGciOiJFZERTQSIsImtpZCI6Imludi0yMDI2LTEwIn0.e30.sig"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: InvocationTokenGrant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"invocation_token": "eyJhbGciOiJFZERTQSIsImtpZCI6Imludi0yMDI2LTEwIn0.e30.signature",
"expires_at": "2026-10-10T09:31:00.000Z"
}
awaitRunInput¶
POST /runs/{run_id}/await-input
Wait for input from a person
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.finishx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: RunAwaitInput
Request
{
"status_line": "Waiting for approval"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Run |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"version": 3,
"billing_mode_expected": "personal",
"model": "model-large",
"status_line": "Reading the export logs",
"metrics": {
"context_pct": 37.5
},
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"steps": {
"0192f4a0-7b1c-7986-8350-06ee441b527a": {
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
},
"followups": {
"0192f4a0-7b1c-77d2-8ef5-9f8e2e1db96b": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "queued"
}
},
"queued_at": "2026-10-10T09:30:00.000Z"
}
finishRun¶
POST /runs/{run_id}/finish
End a run
Repeating the same final state is idempotent and returns 200.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.finishx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Request body (required): application/json: RunFinish
Request
{
"state": "completed",
"reason": "adapter_error",
"summary": "Found the cause and proposed a fix"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Run |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"version": 3,
"billing_mode_expected": "personal",
"model": "model-large",
"status_line": "Reading the export logs",
"metrics": {
"context_pct": 37.5
},
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"steps": {
"0192f4a0-7b1c-7986-8350-06ee441b527a": {
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
},
"followups": {
"0192f4a0-7b1c-77d2-8ef5-9f8e2e1db96b": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "queued"
}
},
"queued_at": "2026-10-10T09:30:00.000Z"
}
answerAutocomplete¶
POST /command-autocompletions/{request_id}/answer
Answer an autocomplete request
The owner of the command answers an open request of command.autocomplete_requested; the
first valid answer goes back to the person. 404 for an unknown or forgotten request,
410 gone after the wait ended, 204 without effect for an answer after the first one.
400 validation_failed for more than command.autocomplete_max_choices choices
(too_many_items), an empty name or value (too_short) or a name or value that is no display
text (invalid_utf8, control_character, bidi_control); the request stays open.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.autocomplete.respondx-rate-limit-class:rl.agent_runtimex-idempotency-exempt:agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
request_id |
path | Uuid | yes |
Request body (required): application/json: AutocompleteAnswer
Request
{
"choices": [
{
"name": "High priority",
"value": "high"
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Runs¶
Runs (live box) for people.
listThreadRuns¶
GET /threads/{thread_id}/runs
List runs of a thread
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: RunSummaryPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"state_reason": "user_cancelled",
"version": 3,
"billing_mode_expected": "personal",
"status_line": "Reading the export logs",
"summary": "Found the cause and proposed a fix",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"step_count": 1,
"queued_at": "2026-10-10T09:30:00.000Z"
}
]
}
listActiveRuns¶
GET /runs
Running now
Runs in queued, running or waiting_input, filtered by run.read.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.overview.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
agent_id |
query | Uuid | no | Only runs of this agent. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: RunSummaryPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"state_reason": "user_cancelled",
"version": 3,
"billing_mode_expected": "personal",
"status_line": "Reading the export logs",
"summary": "Found the cause and proposed a fix",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"step_count": 1,
"queued_at": "2026-10-10T09:30:00.000Z"
}
]
}
getRun¶
GET /runs/{run_id}
Read the run document
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Run |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"version": 3,
"billing_mode_expected": "personal",
"model": "model-large",
"status_line": "Reading the export logs",
"metrics": {
"context_pct": 37.5
},
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"steps": {
"0192f4a0-7b1c-7986-8350-06ee441b527a": {
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
},
"followups": {
"0192f4a0-7b1c-77d2-8ef5-9f8e2e1db96b": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "queued"
}
},
"queued_at": "2026-10-10T09:30:00.000Z"
}
listRunSteps¶
GET /runs/{run_id}/steps
List steps in order
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from the previous page. |
limit |
query | PageLimit | no | Page size. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: RunStepPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-70f2-84b9-bdac58ce716b",
"ordinal": 1,
"kind": "tool_call",
"name": "read_file",
"title": "Reading export.log",
"status": "pending",
"started_at": "2026-10-10T09:30:00.000Z"
}
]
}
getRunContext¶
GET /runs/{run_id}/context
Load the context of an own active run
Agent-self, only for own active runs in queued, running or waiting_input (09, 4.6): the
adapter reads it before startRun. An unknown run, a run the agent cannot see and an own run
that is no longer active answer the same 404; another agent gets 403 forbidden with reason
not_self, a person or an app reason subject_kind_not_allowed. The server computes role and trust of every
element at the time of the request from the current rights; trigger_message is never cut
and never counted, the other parts are cut per element at agent.context_message_max_bytes
and in sum at agent.context_max_bytes from old to new.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.context.readx-rate-limit-class:rl.agent_runtime
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: RunContext |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"run_id": "0192f4a0-7b1c-7c4b-8f0e-4d2a6b1c9e30",
"context_floor_seq": 0,
"trigger_message": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_seq": 42,
"created_at": "2026-10-10T09:30:00.000Z",
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"role": "user",
"origin": "human",
"kind": "text",
"channel_id": "0192f4a0-7b1c-7a1e-9c2d-3b4a5c6d7e8f",
"content_md": "@support-agent the invoice export fails since this morning.",
"attachments": [],
"trust": "trigger"
},
"thread_context": []
}
cancelRun¶
POST /runs/{run_id}/cancel
Cancel a run
Writes run.cancel_requested for the agent. Without confirmation within agent.cancel_grace
the server cancels the run itself.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:run.cancelx-rate-limit-class:rl.trigger
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
run_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: RunCancel
Request
{
"reason": "Wrong ticket"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted; processing continues asynchronously. | application/json: RunSummary |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"state_reason": "user_cancelled",
"version": 3,
"billing_mode_expected": "personal",
"status_line": "Reading the export logs",
"summary": "Found the cause and proposed a fix",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"step_count": 1,
"queued_at": "2026-10-10T09:30:00.000Z"
}
Commands¶
Slash commands, autocomplete, invocation.
listChannelCommands¶
GET /channels/{channel_id}/commands
List commands usable in a channel
Lists the registered commands offered in the channel: those of the channel's effective operator first, then those
of guest agents (only with allow_mentioned_agents) and of apps with write on the channel, an active installation
and the scope commands:write, each group ordered by lower-case name, owner and ID. Per owner and name only the most specific scope appears (channel before space
before instance). The built-in commands are not part of the list; the client shows them from its own list. A dm
channel lists nothing.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CommandList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"owner_principal_id": "0192f4a0-7b1c-7176-8de0-ddf186d11091",
"name": "escalate",
"description": "Escalate the ticket to second level",
"scope_kind": "instance",
"options": [
{
"name": "ticket",
"description": "Ticket number",
"type": "string",
"required": true
}
],
"required_level": "write",
"control": false,
"version": 3
}
]
}
registerCommand¶
POST /commands
Register a command
Registers a command of the calling agent or app. A built-in name answers 409 conflict with reason: command_name_reserved; a name the owner already uses on the same scope target answers 409 conflict without a
reason.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.registerx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: CommandRegister
Request
{
"name": "escalate",
"description": "Escalate the ticket to second level"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Command |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"owner_principal_id": "0192f4a0-7b1c-7176-8de0-ddf186d11091",
"name": "escalate",
"description": "Escalate the ticket to second level",
"scope_kind": "instance",
"options": [
{
"name": "ticket",
"description": "Ticket number",
"type": "string",
"required": true
}
],
"required_level": "write",
"control": false,
"version": 3
}
getCommand¶
GET /commands/{command_id}
Read a command
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
command_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Command |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"owner_principal_id": "0192f4a0-7b1c-7176-8de0-ddf186d11091",
"name": "escalate",
"description": "Escalate the ticket to second level",
"scope_kind": "instance",
"options": [
{
"name": "ticket",
"description": "Ticket number",
"type": "string",
"required": true
}
],
"required_level": "write",
"control": false,
"version": 3
}
updateCommand¶
PUT /commands/{command_id}
Replace a command definition
Replaces the definition of a command of the caller. A built-in name answers 409 conflict with reason: command_name_reserved; a name the owner already uses on the same scope target answers 409 conflict without a
reason. An identical definition answers the command unchanged.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.registerx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
command_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: CommandRegister
Request
{
"name": "escalate",
"description": "Escalate the ticket to second level"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Command |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"owner_principal_id": "0192f4a0-7b1c-7176-8de0-ddf186d11091",
"name": "escalate",
"description": "Escalate the ticket to second level",
"scope_kind": "instance",
"options": [
{
"name": "ticket",
"description": "Ticket number",
"type": "string",
"required": true
}
],
"required_level": "write",
"control": false,
"version": 3
}
removeCommand¶
DELETE /commands/{command_id}
Remove a command
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.removex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
command_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
autocompleteCommand¶
POST /channels/{channel_id}/commands/{command_id}/autocomplete
Get suggestions for an option
Forwards the query to the command owner and waits up to command.autocomplete_timeout; returns
no choices when the owner does not answer in time. Returns an empty list at once when an agent
owner, or an app owner without delivery.interactions_url, has no live gateway connection, when
the installation of the owning app stops being active after the check, and for an agent command in a forum channel without
thread_id after the check (R-AZ-26). An app whose manifest declares delivery.interactions_url
gets the query as a signed POST to that address and has app.interaction_timeout to answer,
never beyond command.autocomplete_timeout: 200 with valid choices returns them, 202 keeps
the request open for answerAutocomplete, any other answer returns an empty list at once (11, 9).
A command of an agent is checked like agent.invoke without a run: a refusal is
403 agent_invocation_denied with reason (for example level_insufficient,
agent_not_reachable, billing_mode_personal_not_holder, tool_class_owner_only,
project_not_ready), a read-only or archived channel 403 channel_read_only. A command of an app
is checked by its required_level and the reachability of the app (active installation,
commands:write, write on the channel), never by the agent.invoke guard; a missing level is
403 agent_invocation_denied with reason, a read-only or archived channel
403 channel_read_only. An unknown, removed or not covered command, an app command whose app is
not reachable, an unknown channel or a thread of another channel is 404.
The query names an option with autocomplete (400 validation_failed with unknown_option,
autocomplete_not_enabled or duplicate; too_long when the request does not fit
sync.event_payload_max_bytes).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.autocompletex-rate-limit-class:rl.triggerx-idempotency-exempt:read_only
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
command_id |
path | Uuid | yes |
Request body (required): application/json: AutocompleteQuery
Request
{
"option": "ticket",
"value": "47"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AutocompleteResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"choices": [
{
"name": "High priority",
"value": "high"
}
]
}
invokeCommand¶
POST /channels/{channel_id}/commands/{command_id}/invoke
Run a command
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:command.invokex-rate-limit-class:rl.trigger
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
command_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: CommandInvoke
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted; processing continues asynchronously. | application/json: CommandInvocation |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"invocation_id": "0192f4a0-7b1c-712e-8ccb-17c85f8d11c9",
"command_id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"accepted": true
}
Apps¶
Installed apps, manifests and scopes.
listApps¶
GET /apps
List installed apps
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AppPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"slug": "ticket-sync",
"display_name": "Ticket Sync",
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"manifest_version": "1.2.0",
"installation": {
"id": "0192f4a0-7b1c-78dc-8da2-d6c386222e8a",
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"state": "active",
"installed_at": "2026-10-10T09:30:00.000Z"
}
}
]
}
installApp¶
POST /apps
Install an app from its manifest
Owner only with a fresh step-up. The manifest is checked against the schema (unknown members give 400 validation_failed with unknown_member) and the check rules of 11, 3.2 (400 validation_failed with the pointers under /manifest; 400 webhook_host_not_allowed when every failure is a delivery host outside webhook.allowed_hosts). granted_scopes holds every required and any optional scope of the manifest; event_subscriptions absent means none, each needs events:subscribe and the scope of the event. One transaction creates the app principal (handle = slug, display name = name), the app and its installation and raises the rights version; nothing is stored on a refusal. No token and no grant is created: grants come per target from createGrant, tokens from createToken. The same slug again is 409 conflict (use upgradeAppManifest); a slug whose apps are all uninstalled reinstalls with the same principal.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.installx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: AppInstall
Request
{
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"reason": "Sync tickets with the help desk"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: App |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"slug": "ticket-sync",
"display_name": "Ticket Sync",
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"manifest_version": "1.2.0",
"installation": {
"id": "0192f4a0-7b1c-78dc-8da2-d6c386222e8a",
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"state": "active",
"installed_at": "2026-10-10T09:30:00.000Z"
}
}
validateManifest¶
POST /app-manifests/validate
Validate a manifest without installing
Owner only. Schema violations give 400 validation_failed; the check rules of 11, 3.2 give 200 with valid false and every rule error, pointers relative to the manifest root. Nothing is stored and no audit entry is written.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.readx-rate-limit-class:rl.readx-idempotency-exempt:read_only
Request body (required): application/json: AppManifest
Request
{
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ManifestValidation |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"valid": false,
"errors": [
{
"pointer": "/delivery/events_url",
"code": "webhook_host_not_allowed",
"detail": "The host is not in webhook.allowed_hosts (R-DM-17, 11 section 3.2 rule 3)."
}
]
}
getApp¶
GET /apps/{app_id}
Read an app
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: App |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"slug": "ticket-sync",
"display_name": "Ticket Sync",
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"manifest_version": "1.2.0",
"installation": {
"id": "0192f4a0-7b1c-78dc-8da2-d6c386222e8a",
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"state": "active",
"installed_at": "2026-10-10T09:30:00.000Z"
}
}
upgradeAppManifest¶
PUT /apps/{app_id}/manifest
Install a new manifest version
Owner only with a fresh step-up (app.install). The new manifest has the same slug and passes the rules of installApp; changed content needs another version (400 at /manifest/version). The upgrade never adds a scope, an event or a grant: granted_scopes and event_subscriptions are subsets of the current ones (a new scope gives 400 at /granted_scopes/<i>; consent with setAppScopes), and event_subscriptions absent keeps the current ones the new manifest and scopes still allow. What the new manifest drops acts at once. New delivery hosts are confirmed by the upgrade itself and must be in webhook.allowed_hosts. An identical manifest with identical lists answers 200 without effect; an uninstalled app is 409 conflict.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.installx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes |
Request body (required): application/json: AppInstall
Request
{
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"reason": "Sync tickets with the help desk"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: App |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"slug": "ticket-sync",
"display_name": "Ticket Sync",
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"manifest_version": "1.2.0",
"installation": {
"id": "0192f4a0-7b1c-78dc-8da2-d6c386222e8a",
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"state": "active",
"installed_at": "2026-10-10T09:30:00.000Z"
}
}
setAppScopes¶
PUT /apps/{app_id}/scopes
Change granted scopes and subscriptions
Owner only with a fresh step-up; the consent for new scopes and events. granted_scopes is a subset of the scopes of the manifest; event_subscriptions absent keeps the current ones the new scopes still allow, present it replaces them (each needs events:subscribe and the scope of the event). A removed scope acts on the next request of every token; a newly granted scope needs a new token, because a token keeps the scopes it was created with. Equal lists answer 200 without effect; an uninstalled app is 409 conflict.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.scopes.updatex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes |
Request body (required): application/json: AppScopesPut
Request
{
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"reason": "Mirror replies into the help desk"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: App |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"slug": "ticket-sync",
"display_name": "Ticket Sync",
"manifest": {
"schema_version": 1,
"slug": "ticket-sync",
"name": "Ticket Sync",
"description": "Mirrors tickets of a help desk into a forum.",
"publisher": "Example Ltd",
"version": "1.2.0",
"homepage_url": "https://apps.example.com/ticket-sync",
"min_api_version": "0.2",
"scopes": {
"required": [
"messages:write"
],
"optional": [
"messages:read",
"events:subscribe"
]
},
"events": [
"message.created"
],
"delivery": {
"mode": "webhook",
"events_url": "https://apps.example.com/ticket-sync/events"
},
"data_egress": "Messages of the granted channels go to apps.example.com."
},
"manifest_version": "1.2.0",
"installation": {
"id": "0192f4a0-7b1c-78dc-8da2-d6c386222e8a",
"granted_scopes": [
"events:subscribe",
"messages:read",
"messages:write"
],
"event_subscriptions": [
"message.created"
],
"state": "active",
"installed_at": "2026-10-10T09:30:00.000Z"
}
}
suspendApp¶
POST /apps/{app_id}/suspend
Suspend an app
Emergency stop without losing grants: tokens blocked, deliveries paused, commands hidden, components disabled (11, 6).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.suspendx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
resumeApp¶
POST /apps/{app_id}/resume
Resume a suspended app
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.resumex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
uninstallApp¶
POST /apps/{app_id}/uninstall
Uninstall an app
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:app.uninstallx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Left the team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Webhooks¶
Outgoing webhook subscriptions and deliveries, incoming webhooks.
listIncomingWebhooks¶
GET /channels/{channel_id}/incoming-webhooks
List incoming webhooks of a channel
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_in.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: IncomingWebhookList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-784b-80fa-070d5a412eea",
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "Monitoring alerts",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createIncomingWebhook¶
POST /channels/{channel_id}/incoming-webhooks
Create an incoming webhook
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_in.createx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: IncomingWebhookCreate
Request
{
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"name": "Monitoring alerts"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: IncomingWebhookCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"webhook": {
"id": "0192f4a0-7b1c-784b-80fa-070d5a412eea",
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"name": "Monitoring alerts",
"created_at": "2026-10-10T09:30:00.000Z"
},
"url": "https://chat.example.com/api/v1/hooks/0192f4a0-7b1c-784b-80fa-070d5a412eea/bothy_whi_EXAMPLE000000000000000000000000000000000000_2WwD3e"
}
revokeIncomingWebhook¶
DELETE /incoming-webhooks/{webhook_id}
Revoke an incoming webhook
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_in.revokex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
postIncomingWebhookWithBearer¶
POST /hooks/{webhook_id}
Post a message through an incoming webhook with the token in Authorization
The token of the incoming webhook is sent as Authorization: Bearer <token>; the path ends with the webhook ID. Use this variant where the sender can set a header, so the token never appears in a URL. Of the root security only bearerAuth applies here, with the token of the incoming webhook; any other scheme or credential counts as a wrong token (404).
The format is recognised per request from the body: a body with at least one Alertmanager member
(version, groupKey, truncatedAlerts, status, receiver, groupLabels, commonLabels,
commonAnnotations, externalURL, alerts) is the unchanged webhook payload of Prometheus
Alertmanager and gives one message per notification; it must carry no native member (400 validation_failed, format_mixed). Every other body is native: Markdown in content_md with
optional title, thread_id and client_msg_id. A format outside webhook_in.formats_enabled
gives 400 validation_failed with format_disabled.
Order of checks (11 8.4): rl.webhook_in of the webhook (429), the token (404), the body up to
webhook_in.max_body_bytes (413), the format (400), authorize of the app (404), then the
message (201). An unknown or revoked webhook, a wrong or malformed token, a suspended or
uninstalled app and every refusal of the app's rights give the same 404. A failed token check
counts against rl.public_auth of the client IP.
The message has origin = app with the app as author, resolves no mentions and never triggers an
agent. native with client_msg_id is idempotent: a repeat answers 200 with the original and
Idempotent-Replay: true, other content with the same client_msg_id 422 idempotency_key_reuse.
Senders inside the stack reach the same path on the internal listener.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_in.postx-rate-limit-class:rl.webhook_inx-idempotency-exempt:client_id
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook_id |
path | Uuid | yes |
Request body (required): application/json: IncomingWebhookPost
native
{
"content_md": "Disk usage above threshold on build host.",
"title": "Disk alert",
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b"
}
alertmanager
{
"version": "4",
"groupKey": "{}:{alertname=\"DiskFull\"}",
"truncatedAlerts": 0,
"status": "firing",
"receiver": "bothy-ops",
"groupLabels": {
"alertname": "DiskFull"
},
"commonLabels": {
"alertname": "DiskFull",
"severity": "warning"
},
"commonAnnotations": {
"summary": "Disk usage above threshold."
},
"externalURL": "https://alertmanager.example.com",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "DiskFull",
"instance": "build.example.com",
"severity": "warning"
},
"annotations": {
"summary": "Disk usage above threshold."
},
"startsAt": "2026-10-10T09:30:00.000Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "https://prometheus.example.com/graph",
"fingerprint": "4a1f0c2b9d3e5f60"
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: IncomingWebhookResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 200 | Replay: the original created by an earlier native request with the same client_msg_id. |
application/json: IncomingWebhookResult |
Correlation-Id, RateLimit, RateLimit-Policy, Idempotent-Replay |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
default
{
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
default
{
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
postIncomingWebhook¶
POST /hooks/{webhook_id}/{token}
Post a message through an incoming webhook
The token is the last path segment; Authorization is ignored. Servers write the path only as its pattern /api/v1/hooks/{webhook_id}/{token} in logs, traces and Problem.instance, and reverse proxies must redact it (16 4.3).
The format is recognised per request from the body: a body with at least one Alertmanager member
(version, groupKey, truncatedAlerts, status, receiver, groupLabels, commonLabels,
commonAnnotations, externalURL, alerts) is the unchanged webhook payload of Prometheus
Alertmanager and gives one message per notification; it must carry no native member (400 validation_failed, format_mixed). Every other body is native: Markdown in content_md with
optional title, thread_id and client_msg_id. A format outside webhook_in.formats_enabled
gives 400 validation_failed with format_disabled.
Order of checks (11 8.4): rl.webhook_in of the webhook (429), the token (404), the body up to
webhook_in.max_body_bytes (413), the format (400), authorize of the app (404), then the
message (201). An unknown or revoked webhook, a wrong or malformed token, a suspended or
uninstalled app and every refusal of the app's rights give the same 404. A failed token check
counts against rl.public_auth of the client IP.
The message has origin = app with the app as author, resolves no mentions and never triggers an
agent. native with client_msg_id is idempotent: a repeat answers 200 with the original and
Idempotent-Replay: true, other content with the same client_msg_id 422 idempotency_key_reuse.
Senders inside the stack reach the same path on the internal listener.
- Security: none
x-authz-action:webhook_in.postx-rate-limit-class:rl.webhook_inx-idempotency-exempt:client_id
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook_id |
path | Uuid | yes | |
token |
path | string | yes | Example: bothy_whi_EXAMPLE000000000000000000000000000000000000_2WwD3e. |
Request body (required): application/json: IncomingWebhookPost
native
{
"content_md": "Disk usage above threshold on build host.",
"title": "Disk alert",
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b"
}
alertmanager
{
"version": "4",
"groupKey": "{}:{alertname=\"DiskFull\"}",
"truncatedAlerts": 0,
"status": "firing",
"receiver": "bothy-ops",
"groupLabels": {
"alertname": "DiskFull"
},
"commonLabels": {
"alertname": "DiskFull",
"severity": "warning"
},
"commonAnnotations": {
"summary": "Disk usage above threshold."
},
"externalURL": "https://alertmanager.example.com",
"alerts": [
{
"status": "firing",
"labels": {
"alertname": "DiskFull",
"instance": "build.example.com",
"severity": "warning"
},
"annotations": {
"summary": "Disk usage above threshold."
},
"startsAt": "2026-10-10T09:30:00.000Z",
"endsAt": "0001-01-01T00:00:00Z",
"generatorURL": "https://prometheus.example.com/graph",
"fingerprint": "4a1f0c2b9d3e5f60"
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: IncomingWebhookResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 200 | Replay: the original created by an earlier native request with the same client_msg_id. |
application/json: IncomingWebhookResult |
Correlation-Id, RateLimit, RateLimit-Policy, Idempotent-Replay |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
default
{
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
listAgentWebhookSubscriptions¶
GET /agents/{agent_id}/webhooks
List webhook subscriptions of an agent
Webhook as transport for adapters without a running process (04, 15.6).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebhookSubscriptionList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7b8e-8d3f-2a9c4e6f0b15",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"url": "https://hooks.example.com/agent",
"event_types": [
"agent.invocation"
],
"state": "active",
"consecutive_failures": 0,
"signature_schemes": [
"v1a"
],
"signing_key_kid": "whk-2026-10",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createAgentWebhookSubscription¶
POST /agents/{agent_id}/webhooks
Subscribe an agent to webhooks
Delivery is strictly in seq order per subscription; 2xx acknowledges up to that seq. Every delivery carries a freshly issued invocation token.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
agent_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: WebhookSubscriptionCreate
Request
{
"url": "https://hooks.example.com/agent",
"event_types": [
"agent.invocation",
"agent.followup",
"run.cancel_requested"
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: WebhookSubscriptionCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listWebhookSubscriptions¶
GET /apps/{app_id}/webhooks
List outgoing webhook subscriptions
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebhookSubscriptionList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7e12-8162-c8db90be34b1",
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"url": "https://hooks.example.com/chat",
"event_types": [
"message.created"
],
"state": "active",
"consecutive_failures": 1,
"signature_schemes": [
"v1a"
],
"signing_key_kid": "whk-2026-10",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createWebhookSubscription¶
POST /apps/{app_id}/webhooks
Subscribe a URL to events
The host and port must be in webhook.allowed_hosts; otherwise 400 webhook_host_not_allowed. With enable_hmac the response carries the v1 secret once; it is a one-time secret, so a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
app_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: WebhookSubscriptionCreate
Request
{
"url": "https://hooks.example.com/chat",
"event_types": [
"message.created"
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: WebhookSubscriptionCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"subscription": {
"id": "0192f4a0-7b1c-7e12-8162-c8db90be34b1",
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"url": "https://hooks.example.com/chat",
"event_types": [
"message.created"
],
"state": "active",
"consecutive_failures": 1,
"signature_schemes": [
"v1a"
],
"signing_key_kid": "whk-2026-10",
"created_at": "2026-10-10T09:30:00.000Z"
},
"hmac_secret": "whsec_EXAMPLE"
}
deleteWebhookSubscription¶
DELETE /webhooks/{subscription_id}
Delete a subscription
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
subscription_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateWebhookSubscription¶
PATCH /webhooks/{subscription_id}
Change, pause or rotate a subscription
A new host must be in webhook.allowed_hosts. rotate_hmac_secret returns the new v1 secret once; it is a one-time secret, so a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
subscription_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: WebhookSubscriptionUpdate
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebhookSubscriptionCreated |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"subscription": {
"id": "0192f4a0-7b1c-7e12-8162-c8db90be34b1",
"app_id": "0192f4a0-7b1c-7895-82f8-463a64ff0fbe",
"url": "https://hooks.example.com/chat",
"event_types": [
"message.created"
],
"state": "active",
"consecutive_failures": 1,
"signature_schemes": [
"v1a"
],
"signing_key_kid": "whk-2026-10",
"created_at": "2026-10-10T09:30:00.000Z"
},
"hmac_secret": "whsec_EXAMPLE"
}
listWebhookDeliveries¶
GET /webhooks/{subscription_id}/deliveries
List delivery attempts
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
subscription_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
status |
query | WebhookDeliveryStatus | no | Filter by status. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: WebhookDeliveryPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-73de-870f-6ce6fa448f1e",
"subscription_id": "0192f4a0-7b1c-756c-88a8-bf72a9fa67f3",
"event_id": "0192f4a0-7b1c-757c-87c8-267db4b2c89f",
"event_seq": 5301,
"event_type": "message.created",
"attempt": 1,
"status": "pending",
"last_error": "timeout",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
redeliverWebhook¶
POST /webhook-deliveries/{delivery_id}/redeliver
Deliver an event again
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:webhook_out.redeliverx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
delivery_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted; processing continues asynchronously. | application/json: WebhookDelivery |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-73de-870f-6ce6fa448f1e",
"subscription_id": "0192f4a0-7b1c-756c-88a8-bf72a9fa67f3",
"event_id": "0192f4a0-7b1c-757c-87c8-267db4b2c89f",
"event_seq": 5301,
"event_type": "message.created",
"attempt": 1,
"status": "pending",
"last_error": "timeout",
"created_at": "2026-10-10T09:30:00.000Z"
}
Audit¶
Audit log query, export and chain verification.
listAuditEvents¶
GET /audit/events
Query the audit log
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:audit.readx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
actor_id |
query | Uuid | no | Actor principal. |
action |
query | string | no | Action ID. |
decision |
query | AuditDecision | no | Decision. |
resource_kind |
query | string | no | Resource kind. |
resource_id |
query | Uuid | no | Resource ID. |
from |
query | Timestamp | no | Occurred at or after. |
to |
query | Timestamp | no | Occurred before. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AuditEventPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"seq": 5301,
"id": "0192f4a0-7b1c-7cb3-8665-8fa2cdd01d12",
"occurred_at": "2026-10-10T09:30:00.000Z",
"action": "grant.create",
"decision": "allow",
"resource_kind": "grant",
"details": {},
"prev_hash": "text",
"hash": "text"
}
]
}
exportAuditEvents¶
GET /audit/export
Export the audit log
Streams one AuditEvent per line in ascending seq, with hashes for offline verification. The stream is the contiguous seq span from the smallest to the largest seq whose occurred_at lies in [from, to), so every line links the line before by prev_hash; a row inside the span whose occurred_at lies outside the range (an aggregated denial keeps the time of its first denial) is part of it. A gap inside the stream breaks the hash links (prev_hash); an error after the first line aborts the transfer instead of ending it, so a client sees a broken response, not a shorter complete one.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:audit.readx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. One JSON object per line (application/x-ndjson). |
application/x-ndjson: AuditEvent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
verifyAuditChain¶
POST /audit/verify
Verify the hash chain
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:audit.verifyx-rate-limit-class:rl.adminx-idempotency-exempt:read_only
Request body (required): application/json: AuditVerifyRequest
Request
{}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: AuditVerifyResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"ok": true,
"checked_from_seq": 1,
"checked_to_seq": 5301,
"checkpoints_compared": 12,
"last_checkpoint_seq": 5290,
"warnings": []
}
Stats¶
Usage, runs, tool calls, errors, costs and prices.
getThreadCosts¶
GET /threads/{thread_id}/costs
Costs of a thread per run
Valid cost entries of the thread (entries no correction supersedes), whatever channel they were booked in, per run (by run_id ascending, unpaginated) and summed per billing mode and currency without conversion. tokens are always present; amounts of runs in mode personal (their costs and their totals) appear only when the server key billing.show_personal_estimates is on (10, 12.2). Never a person: costs stand per run (20, 9). Without read on the thread the same 404 as for an unknown thread. A thread without entries answers empty lists.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:cost.read.threadx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
thread_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CostBreakdown |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"totals": [
{
"billing_mode": "organization",
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
}
],
"runs": [
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"billing_mode": "organization",
"agent_session_id": "0192f4a0-7b1c-7000-8a00-000000000501",
"tokens": {
"tokens_in": 120000,
"tokens_out": 8000,
"tokens_cache_read": 40000,
"tokens_cache_write": 10000,
"tokens_cache_write_1h": 0
},
"costs": [
{
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
}
],
"unpriced": false
},
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a780",
"billing_mode": "personal",
"tokens": {
"tokens_in": 3000,
"tokens_out": 500,
"tokens_cache_read": 0,
"tokens_cache_write": 0,
"tokens_cache_write_1h": 0
},
"unpriced": true
}
]
}
submitClientMetrics¶
POST /client-metrics
Submit anonymous client measurements
Only when privacy.client_metrics is on; otherwise 403 feature_disabled. At most once per client.metrics.flush_interval (15, section 17).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:client_metrics.submitx-rate-limit-class:rl.writex-idempotency-exempt:telemetry
Request body (required): application/json: ClientMetricsBatch
Request
{
"platform": "ios",
"app_version": "1.4.0",
"density": "touch",
"metrics": [
{
"name": "client.thread_open.duration",
"kind": "histogram",
"buckets": [
{
"le": 0.1,
"count": 12
},
{
"le": 0.25,
"count": 3
}
]
},
{
"name": "client.reconnects",
"kind": "counter",
"close_code": 4009,
"value": 1
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
getUsageStats¶
GET /stats/usage
Usage per space
Metrics per space and bucket: messages (messages not deleted) and by origin messages_human, messages_agent, messages_app, messages_import; threads_created, threads_done (threads closed in the bucket); runs (runs that ended in the bucket); active_people (distinct people with at least one message, only for granularity week or month; below privacy.stats_min_group_size the value is withheld and named in below_min_group); storage_bytes (current sum of the files of the space, in the last bucket only). Grouped by space (group_key is the space ID). Authorized with stats.read on the instance (owner) or, with space_id, on that space (manage); without space_id and without owner status 403, an unreadable space 404. Every number of a channel counts only the channels the caller may read (message.read), intersected with the space; channels without a space (DMs) are not counted. No metric is grouped by person and no person is named. from and to are aligned down and up to the granularity (default day): hour in UTC, day, week (ISO, Monday) and month from local midnight of stats.time_zone, returned as UTC instants; a range longer than stats.max_range, with more than api.stats_max_buckets buckets or with from >= to is 400 validation_failed. Buckets without a value are left out. The result is cached per caller scope for stats.cache_ttl.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
granularity |
query | StatsGranularity | no | Bucket size; default day. |
space_id |
query | Uuid | no | Restrict to a space; required without owner role. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsSeries |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"granularity": "hour",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"group_key": "0192f4a0-7b1c-7000-8a00-000000000101",
"metrics": {}
}
]
}
getRunStats¶
GET /stats/runs
Runs per agent
Metrics per agent and bucket of the end of a run: runs, completed, failed, cancelled, duration_ms_p50, duration_ms_p95 (from start to end of the runs that started), and failed_reason_<code> for every state_reason code of failed runs that occurs. Grouped by agent (group_key is the agent ID). Authorized with stats.read on the instance (owner) or, with space_id, on that space (manage); without space_id and without owner status 403, an unreadable space 404. Every number of a channel counts only the channels the caller may read (message.read), intersected with the space; channels without a space (DMs) are not counted. No metric is grouped by person and no person is named. from and to are aligned down and up to the granularity (default day): hour in UTC, day, week (ISO, Monday) and month from local midnight of stats.time_zone, returned as UTC instants; a range longer than stats.max_range, with more than api.stats_max_buckets buckets or with from >= to is 400 validation_failed. Buckets without a value are left out. The result is cached per caller scope for stats.cache_ttl.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
granularity |
query | StatsGranularity | no | Bucket size; default day. |
space_id |
query | Uuid | no | Restrict to a space. |
agent_id |
query | Uuid | no | Restrict to an agent. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsSeries |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"granularity": "hour",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"group_key": "0192f4a0-7b1c-7000-8a00-000000000101",
"metrics": {}
}
]
}
getToolCallStats¶
GET /stats/tool-calls
Tool calls by tool name
Metrics per tool name and bucket of the start of the call: calls, failed, duration_ms_p50 (finished calls). Grouped by the tool name from run_steps (group_key); no step detail, no input and no output. Authorized with stats.read on the instance (owner) or, with space_id, on that space (manage); without space_id and without owner status 403, an unreadable space 404. Every number of a channel counts only the channels the caller may read (message.read), intersected with the space; channels without a space (DMs) are not counted. No metric is grouped by person and no person is named. from and to are aligned down and up to the granularity (default day): hour in UTC, day, week (ISO, Monday) and month from local midnight of stats.time_zone, returned as UTC instants; a range longer than stats.max_range, with more than api.stats_max_buckets buckets or with from >= to is 400 validation_failed. Buckets without a value are left out. The result is cached per caller scope for stats.cache_ttl.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
granularity |
query | StatsGranularity | no | Bucket size; default day. |
space_id |
query | Uuid | no | Restrict to a space. |
agent_id |
query | Uuid | no | Restrict to an agent. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsSeries |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"granularity": "hour",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"group_key": "0192f4a0-7b1c-7000-8a00-000000000101",
"metrics": {}
}
]
}
getErrorStats¶
GET /stats/errors
Error rates of runs and deliveries
Metrics per bucket: run_failure_rate (failed per ended runs), invocation_denials (messages refused with billing_mode_personal_not_holder plus runs failed with billing_mode_mismatch); only for the instance (owner, without space_id): webhook_failure_rate (failed and dead per finished deliveries still within their retention), push_failure_rate_<provider> (registrations disabled for a provider reason per registrations active in the bucket), scan_errors and scan_infected; these have no channel and count the whole instance. A rate without a denominator is left out. Without space_id there is no group_key; with space_id it is the space ID. HTTP error rates come from telemetry, not from this API. Authorized with stats.read on the instance (owner) or, with space_id, on that space (manage); without space_id and without owner status 403, an unreadable space 404. Every number of a channel counts only the channels the caller may read (message.read), intersected with the space; channels without a space (DMs) are not counted. No metric is grouped by person and no person is named. from and to are aligned down and up to the granularity (default day): hour in UTC, day, week (ISO, Monday) and month from local midnight of stats.time_zone, returned as UTC instants; a range longer than stats.max_range, with more than api.stats_max_buckets buckets or with from >= to is 400 validation_failed. Buckets without a value are left out. The result is cached per caller scope for stats.cache_ttl.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
granularity |
query | StatsGranularity | no | Bucket size; default day. |
space_id |
query | Uuid | no | Restrict to a space. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsSeries |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"granularity": "hour",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"group_key": "0192f4a0-7b1c-7000-8a00-000000000101",
"metrics": {}
}
]
}
getCostStats¶
GET /stats/costs
Costs per space, agent or instance
Valid cost sums (entries without a successor) per bucket and billing_mode, grouped by group_by (space, agent, none; default none). Authorized with cost.read.aggregate on the instance (owner) or, with space_id, on that space (manage); without space_id and without owner status 403, an unreadable space 404; only channels the caller may read count. personal and organization are never summed together; amounts of mode personal are information only and appear only when billing.show_personal_estimates is on. is_estimate is true when any summed entry is an estimate. One currency per response: currency selects it; without it a range whose entries have one currency answers in that currency (USD when there is none), and a range with several currencies is 400 validation_failed with errors[].code currency_required and the currencies found in detail. Ranges, buckets, time zone and cache as for getUsageStats.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:cost.read.aggregatex-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
granularity |
query | StatsGranularity | no | Bucket size; default day. |
group_by |
query | string | no | Grouping of the buckets; default none. Values: space, agent, none. |
space_id |
query | Uuid | no | Restrict to a space. |
agent_id |
query | Uuid | no | Restrict to an agent. |
currency |
query | string | no | ISO 4217 code of the costs to sum; required when the range has costs in several currencies. Pattern ^[A-Z]{3}$. Example: USD. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CostSeries |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"granularity": "hour",
"currency": "USD",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"billing_mode": "personal",
"amount_micros": 1,
"is_estimate": true
}
]
}
getStatsLive¶
GET /stats/live
Current live frame
The latest live frame (StatsLiveFrame) of the instance or of one space, the same frame the gateway sends as stats.live (docs/spec/25-visualization.md, section 5). The server returns the base frame built for the current stats.live_interval; polling does not rebuild it. Filtered to the channels visible to the caller; cost members only with cost.read.aggregate. 403 feature_disabled when stats.live_enabled is off.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
space_id |
query | Uuid | no | Restrict to a space; required without owner role. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsLiveFrame |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"at": "2026-10-10T09:30:00.000Z",
"interval_ms": 1000,
"scope": {
"kind": "instance"
},
"runs": [
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"thread_id": "0192f4a0-7b1c-7000-8a00-000000000301",
"channel_id": "0192f4a0-7b1c-7000-8a00-000000000201",
"space_id": "0192f4a0-7b1c-7000-8a00-000000000101",
"agent_id": "0192f4a0-7b1c-7000-8a00-000000000401",
"state": "running",
"queued_at": "2026-10-10T09:29:10.000Z",
"started_at": "2026-10-10T09:29:11.000Z",
"billing_mode": "organization",
"step": {
"kind": "tool_call",
"name": "Bash"
},
"approval_pending": false,
"cost_micros": 420000,
"currency": "USD",
"cost_is_estimate": true
}
],
"runs_truncated": false,
"agents": [
{
"agent_id": "0192f4a0-7b1c-7000-8a00-000000000401",
"presence": "online",
"billing_mode": "organization",
"reported_billing_mode": "organization",
"rate_limit": {
"state": "ok"
}
}
],
"rates": [
{
"metric": "messages_created",
"last_minute": 14,
"current_minute": 3
}
],
"sli": [
{
"metric": "sli.delivery_latency",
"total": 5210,
"good": 5207,
"ratio": 0.99942
}
]
}
getStatsTimeline¶
GET /stats/timeline
Minute buckets and runs for playback
Minute aggregates from stats_minutes and run intervals for a range of at most stats.timeline_max_range inside retention.stats_minutes (docs/spec/25-visualization.md, section 6.5). Filtered to the channels visible to the caller. Rows without a channel (sli.*, gateway metrics) only with stats.read on the instance; cost only with cost.read.aggregate.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive), a full minute. |
to |
query | Timestamp | yes | End of the range (exclusive), a full minute. |
space_id |
query | Uuid | no | Restrict to a space; required without owner role. |
metric |
query | array of StatsMetric | no | Metrics to return; absent means all metrics the caller may see. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsTimeline |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"from": "2026-10-10T00:00:00.000Z",
"to": "2026-10-11T00:00:00.000Z",
"buckets": [
{
"start": "2026-10-10T09:30:00.000Z",
"metric": "runs_finished",
"channel_id": "0192f4a0-7b1c-7000-8a00-000000000201",
"agent_id": "0192f4a0-7b1c-7000-8a00-000000000401",
"dimension": "completed",
"count": 2,
"sum": 84000,
"good": 0
}
],
"runs": [
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"channel_id": "0192f4a0-7b1c-7000-8a00-000000000201",
"agent_id": "0192f4a0-7b1c-7000-8a00-000000000401",
"queued_at": "2026-10-10T09:29:10.000Z",
"started_at": "2026-10-10T09:29:11.000Z",
"finished_at": "2026-10-10T09:30:35.000Z",
"state": "completed"
}
],
"runs_truncated": false
}
getStatsSlo¶
GET /stats/slo
SLO traffic light from own measurement
One entry per SLO of the Sloth files, computed from stats_minutes over the SLO period (docs/spec/25-visualization.md, section 6.4). Label "own measurement": values may differ from Prometheus. Requires stats.read on the instance (owner); a space manager gets 403 forbidden.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsSloReport |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"at": "2026-10-10T09:30:00.000Z",
"measured_by": "own",
"items": [
{
"slo": "bothy-sync/delivery-latency",
"metric": "sli.delivery_latency",
"objective": 99.5,
"threshold_ms": 500,
"period_days": 30,
"total": 1250000,
"good": 1246100,
"ratio": 0.99688,
"budget_remaining": 0.376,
"state": "green"
}
]
}
getStatsBackends¶
GET /stats/backends
Backend policy view per agent
Per agent: configured and reported billing mode, supported modes, switches, denied invocations (I2, I3), cost per mode and the rate-limit state reported by the adapter (docs/spec/25-visualization.md, section 6.2). Agents of channels visible to the caller; cost members only with cost.read.aggregate. Never credentials, subscriptions or runtime names of an instance.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:stats.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
space_id |
query | Uuid | no | Restrict to a space; required without owner role. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatsBackendReport |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"agent_id": "0192f4a0-7b1c-7000-8a00-000000000401",
"billing_mode": "organization",
"reported_billing_mode": "organization",
"billing_modes_supported": [
"organization"
],
"switches": 1,
"invocations_denied": {
"i2_denied": 0,
"billing_mode_mismatch": 0
},
"costs": [
{
"billing_mode": "organization",
"currency": "USD",
"amount_micros": 12400000,
"is_estimate": true
}
],
"rate_limit": {
"state": "near_limit",
"resets_at": "2026-10-10T10:00:00.000Z"
}
}
]
}
listPrices¶
GET /prices
List prices
Every row of the price table, closed ones included, ordered by provider, model, unit, valid_from and id; valid_to is absent while a row is open. A small unpaginated list (06, 6 point 6). Owner only; an owner's personal token gets 403.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:price.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: PriceList |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7096-8437-e1ee469c906c",
"provider": "anthropic",
"model": "model-large",
"unit": "input_mtok",
"price_micros": 1,
"currency": "USD",
"valid_from": "2026-10-10T09:30:00.000Z",
"source_url": "https://provider.example.com/pricing",
"retrieved_at": "2026-10-10T09:30:00.000Z"
}
]
}
createPrice¶
POST /prices
Add a price with source
Owner with step-up, audited with row, source and retrieval time (10, 14). source_url is an absolute https URL without user info and fragment, retrieved_at not in the future, currency an ISO 4217 code. 409 conflict with reason price_overlap when the validity overlaps a row of the same provider, model and unit, price_currency_mismatch when an overlapping row of the same provider and model has another currency (one currency per price set).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:price.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: PriceCreate
Request
{
"provider": "anthropic",
"model": "model-large",
"unit": "input_mtok",
"price_micros": 1,
"currency": "USD",
"valid_from": "2026-10-10T09:30:00.000Z",
"source_url": "https://provider.example.com/pricing",
"retrieved_at": "2026-10-10T09:30:00.000Z"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: Price |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7096-8437-e1ee469c906c",
"provider": "anthropic",
"model": "model-large",
"unit": "input_mtok",
"price_micros": 1,
"currency": "USD",
"valid_from": "2026-10-10T09:30:00.000Z",
"source_url": "https://provider.example.com/pricing",
"retrieved_at": "2026-10-10T09:30:00.000Z"
}
closePrice¶
POST /prices/{price_id}/close
End the validity of a price
Sets valid_to of an open row, the only change a row ever gets (R-DM-23). The same end again answers 200 without change. 409 conflict with reason price_closed when the row is already closed with another end (a closed row is never reopened or moved; a gap is filled by a new row), price_in_use when a computed cost entry at or after the new end used the row.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:price.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
price_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: PriceClose
Request
{
"valid_to": "2026-10-10T09:30:00.000Z"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Price |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7096-8437-e1ee469c906c",
"provider": "anthropic",
"model": "model-large",
"unit": "input_mtok",
"price_micros": 1,
"currency": "USD",
"valid_from": "2026-10-10T09:30:00.000Z",
"source_url": "https://provider.example.com/pricing",
"retrieved_at": "2026-10-10T09:30:00.000Z"
}
reconcileCosts¶
POST /costs/reconcile
Reconcile estimates with invoices
For an owner in a session with a fresh step-up; app, agent and personal tokens are refused (05, R-AZ-03). Stores new reconciled entries next to the estimates and never changes or deletes an entry (10, 12.4). An entry is matched when its run has at least one valid cost entry with occurred_at in the half-open period [period_start, period_end) and all of them have mode organization, the given provider and the entry's currency; otherwise its run ID is listed in unmatched_run_ids. The amount of a matched run is split over its valid entries in the period in proportion to their amounts, the remainder on the largest entry; a run whose valid entries in the period are already reconciled with the same sum is not written again. The job billing.reconcile then applies the entries to the run and agent session totals.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:cost.reconcilex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: CostReconcile
Request
{
"provider": "anthropic",
"period_start": "2026-10-10T09:30:00.000Z",
"period_end": "2026-10-10T09:30:00.000Z",
"entries": [
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"amount_micros": 1,
"currency": "USD"
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CostReconcileResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"reconciled": 1,
"unmatched_run_ids": [
"0192f4a0-7b1c-7250-807f-c268a7b21797"
]
}
submitCostReconciliation¶
POST /costs/reconciliations
Submit reconciled cost entries (app)
For the reconciliation app with scope costs:reconcile, without step-up. Only adds reconciled entries to existing runs; deletes nothing (10, 12.4). Matching, period, split and repeat rules as reconcileCosts: an entry is matched when its run has at least one valid cost entry with occurred_at in [period_start, period_end) and all of them have mode organization, the given provider and the entry's currency; unmatched run IDs are listed in unmatched_run_ids; a run already reconciled with the same sum is not written again. The job billing.reconcile then applies the entries to the run and agent session totals.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:cost.reconcile.submitx-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: CostReconcile
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CostReconcileResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listCostEstimates¶
GET /costs/estimates
Cost estimates per run for reconciliation
For the reconciliation app with scope costs:reconcile and for owners in a session, without step-up (05, R-AZ-28). One item per run of the given agents with cost entries of mode organization whose occurred_at lies in the range, sorted by run_id; runs whose entries in the range mix currencies are left out. Entries of mode personal never appear (03 cost_entries). Items name no channel, thread or content; the list is evaluated on the instance and not filtered by visible channels (06, 4 point 2).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:cost.reconcile.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
agent_id |
query | array of Uuid | yes | Agents whose runs are listed; repeat the parameter for several agents. Min items 1. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: CostEstimatePage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"run_id": "0192f4a0-7b1c-70cd-8013-27d7ac09a77f",
"agent_id": "0192f4a0-7b1c-7250-807f-c268a7b21797",
"provider": "anthropic",
"currency": "USD",
"estimate_micros": 1250000,
"reconciled": false
}
]
}
Status¶
Status page.
getStatus¶
GET /status
Status page
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.readx-rate-limit-class:rl.read
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatusPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"overall_state": "operational",
"components": [
{
"id": "0192f4a0-7b1c-7cbd-8bdb-de45278e4e7b",
"name": "Messages",
"description": "Support team",
"sort_key": "a0",
"state": "operational",
"health_source": "db",
"updated_at": "2026-10-10T09:30:00.000Z"
}
],
"incidents": [
{
"id": "0192f4a0-7b1c-7b46-88f5-a7d58fbd8809",
"title": "Push notifications delayed",
"kind": "incident",
"impact": "none",
"state": "scheduled",
"started_at": "2026-10-10T09:30:00.000Z",
"component_ids": [
"0192f4a0-7b1c-790b-86bb-302f588b2602"
],
"updates": [
{
"id": "0192f4a0-7b1c-7d72-8102-dd7af4afabb5",
"state": "scheduled",
"body_md": "The push provider reports delays. We are monitoring.",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
]
}
getPublicStatus¶
GET /status/public
Status page without login
404 unless status.public_enabled.
- Security: none
x-authz-action:status.public.readx-rate-limit-class:rl.public_auth
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatusPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"overall_state": "operational",
"components": [
{
"id": "0192f4a0-7b1c-7cbd-8bdb-de45278e4e7b",
"name": "Messages",
"description": "Support team",
"sort_key": "a0",
"state": "operational",
"health_source": "db",
"updated_at": "2026-10-10T09:30:00.000Z"
}
],
"incidents": [
{
"id": "0192f4a0-7b1c-7b46-88f5-a7d58fbd8809",
"title": "Push notifications delayed",
"kind": "incident",
"impact": "none",
"state": "scheduled",
"started_at": "2026-10-10T09:30:00.000Z",
"component_ids": [
"0192f4a0-7b1c-790b-86bb-302f588b2602"
],
"updates": [
{
"id": "0192f4a0-7b1c-7d72-8102-dd7af4afabb5",
"state": "scheduled",
"body_md": "The push provider reports delays. We are monitoring.",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
]
}
createStatusComponent¶
POST /status/components
Add a status component
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: StatusComponentInput
Request
{
"name": "Messages"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: StatusComponent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7cbd-8bdb-de45278e4e7b",
"name": "Messages",
"description": "Support team",
"sort_key": "a0",
"state": "operational",
"health_source": "db",
"updated_at": "2026-10-10T09:30:00.000Z"
}
deleteStatusComponent¶
DELETE /status/components/{component_id}
Remove a status component
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
component_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | No content. | Correlation-Id, RateLimit, RateLimit-Policy | |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
updateStatusComponent¶
PATCH /status/components/{component_id}
Change a status component
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
component_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: StatusComponentInput
Request
{
"name": "Messages"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: StatusComponent |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7cbd-8bdb-de45278e4e7b",
"name": "Messages",
"description": "Support team",
"sort_key": "a0",
"state": "operational",
"health_source": "db",
"updated_at": "2026-10-10T09:30:00.000Z"
}
createStatusIncident¶
POST /status/incidents
Open an incident or maintenance
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: StatusIncidentCreate
Request
{
"title": "Push notifications delayed",
"kind": "incident",
"impact": "none",
"started_at": "2026-10-10T09:30:00.000Z",
"component_ids": [
"0192f4a0-7b1c-790b-86bb-302f588b2602"
],
"body_md": "The push provider reports delays."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: StatusIncident |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7b46-88f5-a7d58fbd8809",
"title": "Push notifications delayed",
"kind": "incident",
"impact": "none",
"state": "scheduled",
"started_at": "2026-10-10T09:30:00.000Z",
"component_ids": [
"0192f4a0-7b1c-790b-86bb-302f588b2602"
],
"updates": [
{
"id": "0192f4a0-7b1c-7d72-8102-dd7af4afabb5",
"state": "scheduled",
"body_md": "The push provider reports delays. We are monitoring.",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
addStatusIncidentUpdate¶
POST /status/incidents/{incident_id}/updates
Add an update to an incident
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:status.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
incident_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: StatusIncidentUpdateCreate
Request
{
"state": "scheduled",
"body_md": "Delays are resolved."
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: StatusIncident |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7b46-88f5-a7d58fbd8809",
"title": "Push notifications delayed",
"kind": "incident",
"impact": "none",
"state": "scheduled",
"started_at": "2026-10-10T09:30:00.000Z",
"component_ids": [
"0192f4a0-7b1c-790b-86bb-302f588b2602"
],
"updates": [
{
"id": "0192f4a0-7b1c-7d72-8102-dd7af4afabb5",
"state": "scheduled",
"body_md": "The push provider reports delays. We are monitoring.",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
Import¶
Import jobs.
listImports¶
GET /imports
List import sources
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSourcePage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createImport¶
POST /imports
Add an import source
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ImportSourceCreate
Request
{
"kind": "discord",
"name": "Old community server",
"config": {}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
getImport¶
GET /imports/{import_id}
Read progress of an import
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
listImportItems¶
GET /imports/{import_id}/items
List imported items
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
state |
query | ImportItemState | no | Filter by state. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportItemPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7e43-8919-6113546a4c70",
"origin_key": "message:1029384756:0",
"item_kind": "space",
"state": "pending",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
startImport¶
POST /imports/{import_id}/start
Start or continue an import
Moves a draft or paused source to running (22, 7.4); started_at is set on the first start. Starting a running source answers it unchanged. Any other state is 409 conflict with reason import_state.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 202 | Accepted; processing continues asynchronously. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
pauseImport¶
POST /imports/{import_id}/pause
Pause an import
Moves a running source to paused; batches and cursor writes then answer 409 conflict with reason import_not_running. Pausing a paused source answers it unchanged. Any other state is 409 conflict with reason import_state.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
cancelImport¶
POST /imports/{import_id}/cancel
Cancel an import
Ends a draft, running or paused source as failed with the counter server.cancelled set to true in stats and sets finished_at. Any other state is 409 conflict with reason import_state.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "draft",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
completeImport¶
POST /imports/{import_id}/complete
Complete an import
When every channel is led by this server: stop the mirror, source completed (22, 13.5).
Only from running or paused, else 409 conflict with reason import_state. Every channel of the mapping whose target is not skip and whose channel item is posted must have lead = bothy, else 409 conflict with reason lead_not_bothy; mapped channels that were never imported do not block it.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "completed",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
setImportLead¶
PUT /imports/{import_id}/leads
Set the leading side of a channel
Switches lead of one mapped channel and the read-only state of its target channel in one transaction (22, 12.1 and 13).
The channel must be in the mapping with a target other than skip (else 404) and its channel item must be posted (else 409 conflict with reason channel_not_imported). lead = discord sets the target channel read-only and cancels its active runs; lead = bothy lifts read-only. A completed or failed source is 409 conflict with reason import_state. A lead equal to the current one changes nothing.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes |
Request body (required): application/json: ImportLeadSet
Request
{
"source_channel": "1029384000",
"lead": "bothy"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "completed",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
applyImportBatch¶
POST /imports/{import_id}/batches
Write a batch of imported objects
One transaction, at most import.batch_max_items objects. Every target must lie in a channel of this running source. Existing posted keys return their target without a duplicate or event (22, 7.2). Writes thread.updated and import.progress instead of one event per message.
A source that is not running is 409 conflict with reason import_not_running; a target outside the channels of the source is 409 conflict with reason target_outside_source; a new channel whose name equals a live channel of its space is 409 conflict with reason name_collision. The data of a structure item follows ImportSpaceData, ImportChannelData, ImportForumTagData or ImportUserData.
A batch with thread_origin_key concerns exactly one thread (thread:<id>, or channel:<id> for the main thread of a text channel; a forum has none, 400 validation_failed). Its optional first item is the thread item of that key (ImportThreadData), every other item a message (ImportMessageData) or a pin (ImportPinData); a structure item there, or a content item in a batch without thread_origin_key, is 400 validation_failed at its item_kind. A thread that is neither posted nor created by the batch is 409 conflict with reason thread_not_imported; a message whose author item is not posted 409 conflict with reason author_not_imported. Imported messages have origin = import, are silent, write no mentions and never trigger an agent; a posted thread only follows the mirror rules of 22 12.2 step 3. At its end a batch that changed something sets threads.unread_floor_seq to the end of the thread and appends one thread.updated and one import.progress, never message.created (04 15.8).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.applyx-rate-limit-class:rl.importx-idempotency-exempt:origin_key
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes |
Request body (required): application/json: ImportBatch
Request
{
"thread_origin_key": "thread:1029384700",
"items": [
{
"origin_key": "message:1029384756",
"item_kind": "message",
"data": {
"author_origin_key": "user:1029384000",
"content_md": "The invoice export fails.",
"created_at": "2025-03-01T08:00:00.000Z"
}
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportBatchResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7e43-8919-6113546a4c70",
"origin_key": "message:1029384756",
"item_kind": "message",
"target_kind": "message",
"target_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"state": "posted",
"created_at": "2026-10-10T09:30:00.000Z"
}
],
"unread_floor_seq": 42
}
createImportFile¶
POST /imports/{import_id}/files
Reserve an imported file
Writes the pending item and reserves the file ID with an upload session of mode direct, without the quota check of createUpload (12, 11); the parts and the completion follow through uploadImportFilePart and completeImportFile, which a read-only mirror channel accepts (05 rule 1.8). A repeated call with the same key returns the same ID: with the open session, with a new session after an aborted or expired one, and without upload once the item is posted (22, 7.2). channel_id must be the target of a posted channel item of the source (409 conflict, reason target_outside_source), author_id the target of a posted user item (409 conflict, reason author_not_imported); the scan of an import file runs with the lowest job priority.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.applyx-rate-limit-class:rl.importx-idempotency-exempt:origin_key
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes |
Request body (required): application/json: ImportFileCreate
Request
{
"origin_key": "file:1029384799",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"author_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"name": "report.pdf",
"size_bytes": 48213,
"sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportFileSlot |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
uploadImportFilePart¶
PUT /imports/{import_id}/files/{file_id}/parts/{part_number}
Upload one part of an imported file
One part of the file of a file item of this source in mode direct, with the rules of uploadPart (12, 3.2): the same part number with the same Content-Digest answers 200 without new work, with another digest 409 conflict with reason part_conflict; a wrong length or digest is 400 validation_failed with errors[].code part_digest_mismatch and stores nothing; an expired session answers 410 gone (a repeated createImportFile opens a new one). It authorizes import.apply on the running source instead of file.upload, so a read-only mirror channel accepts it (05 rule 1.8, 4.12). A file that is not the target of a file item of this source is 404.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.applyx-rate-limit-class:rl.import
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
file_id |
path | Uuid | yes | |
part_number |
path | integer | yes | Minimum 1. |
Content-Digest |
header | string | yes | RFC 9530 digest of the part with the member sha-256, e.g. sha-256=:<base64>:; other members are ignored. |
Request body (required): application/octet-stream: string (binary)
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: UploadPartResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 413 | PayloadTooLarge: Problem codes: payload_too_large. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"part_number": 1,
"etag": "\"3858f62230ac3c915f300c664312c11f\""
}
completeImportFile¶
POST /imports/{import_id}/files/{file_id}/complete
Finish the upload of an imported file
Completes the upload of the file of a file item of this source with the rules of completeUpload (12, 3.4): parts is checked against the confirmed parts, missing parts are 409 conflict with reason upload_incomplete, another etag 409 conflict with reason part_conflict, an expired session 410 gone. The job files.scan checks size and SHA-256 against the declaration of createImportFile, detects the type and scans; it runs with the lowest job priority, so live uploads are scanned first (12, 11). The item becomes posted in the same transaction; a repeated call answers the posted item. It authorizes import.apply on the running source instead of file.upload (05 rule 1.8, 4.12). A file that is not the target of a file item of this source is 404.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.applyx-rate-limit-class:rl.importx-idempotency-exempt:origin_key
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes | |
file_id |
path | Uuid | yes |
Request body (required): application/json: UploadComplete
Request
{
"parts": [
{
"part_number": 1,
"etag": "\"3858f62230ac3c915f300c664312c11f\""
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportFileSlot |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"item": {
"id": "0192f4a0-7b1c-7e43-8919-6113546a4c71",
"origin_key": "file:1029384799",
"item_kind": "file",
"target_kind": "file",
"target_id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"state": "posted",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
setImportCursor¶
PUT /imports/{import_id}/cursor
Advance the import cursor
Only after a successful batch (22, 7.3).
Replaces cursor with the given object and merges the top-level members of stats into the member tool of ImportSource.stats (the server's own counters stay under server). Only for a running source, else 409 conflict with reason import_not_running.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:import.applyx-rate-limit-class:rl.import
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
import_id |
path | Uuid | yes |
Request body (required): application/json: ImportCursorSet
Request
{
"cursor": {}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: ImportSource |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-78d2-8a6a-ec465435b8a0",
"kind": "discord",
"name": "Old community server",
"config": {},
"state": "completed",
"stats": {},
"created_at": "2026-10-10T09:30:00.000Z"
}
Privacy¶
Privacy requests and exports.
exportChannel¶
GET /channels/{channel_id}/export
Export the history of a channel
Streams one Message per line in thread_seq order per thread. Requires step-up.
from must be strictly before to, else 400 validation_failed at #query/to with code
invalid; the range has no upper bound, so clients split long ranges. Each line carries the
full content_md without content_truncated and without my_reactions; deleted messages
appear as tombstones at their thread_seq. Threads come ascending by id, the messages of a
thread ascending by thread_seq. Read rights are checked again before every batch, so a
revocation ends the stream. An export cut after the first byte ends without a complete
response (no final chunk); a range without messages gives 200 with an empty body.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:export.channelx-rate-limit-class:rl.export
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
channel_id |
path | Uuid | yes | |
from |
query | Timestamp | yes | Start of the range (inclusive). |
to |
query | Timestamp | yes | End of the range (exclusive). |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. One JSON object per line (application/x-ndjson). |
application/x-ndjson: Message |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
listGdprRequests¶
GET /gdpr-requests
List privacy requests
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:gdpr.request.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
subject_user_id |
query | Uuid | no | Only requests about this person. |
state |
query | GdprRequestState | no | Filter by state. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GdprRequestPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7ac0-85c3-2e83fd50d9e7",
"subject_user_id": "0192f4a0-7b1c-7277-8379-95fe87046d8a",
"kind": "export",
"state": "requested",
"requested_by": "0192f4a0-7b1c-7e23-8a0f-0b7e316bfc58",
"reason": "Request by the person",
"due_at": "2026-10-10T09:30:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
}
]
}
createGdprRequest¶
POST /gdpr-requests
Request export, deletion or rectification
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:gdpr.request.createx-rate-limit-class:rl.export
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GdprRequestCreate
Request
{
"kind": "export",
"reason": "Request by the person"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: GdprRequest |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7ac0-85c3-2e83fd50d9e7",
"subject_user_id": "0192f4a0-7b1c-7277-8379-95fe87046d8a",
"kind": "export",
"state": "requested",
"requested_by": "0192f4a0-7b1c-7e23-8a0f-0b7e316bfc58",
"reason": "Request by the person",
"due_at": "2026-10-10T09:30:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
}
getGdprRequest¶
GET /gdpr-requests/{request_id}
Read a privacy request
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:gdpr.request.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
request_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GdprRequest |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7ac0-85c3-2e83fd50d9e7",
"subject_user_id": "0192f4a0-7b1c-7277-8379-95fe87046d8a",
"kind": "export",
"state": "requested",
"requested_by": "0192f4a0-7b1c-7e23-8a0f-0b7e316bfc58",
"reason": "Request by the person",
"due_at": "2026-10-10T09:30:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
}
decideGdprRequest¶
POST /gdpr-requests/{request_id}/decide
Approve or reject a privacy request
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:gdpr.request.decidex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
request_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: GdprDecision
Request
{
"decision": "approve",
"reason": "Identity verified"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: GdprRequest |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7ac0-85c3-2e83fd50d9e7",
"subject_user_id": "0192f4a0-7b1c-7277-8379-95fe87046d8a",
"kind": "export",
"state": "requested",
"requested_by": "0192f4a0-7b1c-7e23-8a0f-0b7e316bfc58",
"reason": "Request by the person",
"due_at": "2026-10-10T09:30:00.000Z",
"created_at": "2026-10-10T09:30:00.000Z"
}
downloadGdprExport¶
GET /gdpr-requests/{request_id}/export
Download the export package
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:gdpr.export.downloadx-rate-limit-class:rl.export
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
request_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/zip: string (binary) |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 410 | Gone: Problem codes: resync_required, message_deleted, gone. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Hosts¶
Connected hosts for the terminal: registration, pairing, fingerprint, LLM login declaration (I6).
listHosts¶
GET /hosts
List hosts
Owners see every host; other people see hosts they are assigned to or hold a terminal grant on (07, 2.12). Ordered by name.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: HostPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
]
}
createHost¶
POST /hosts
Register a host and issue its pairing code
Creates a host in state pairing and returns the pairing code bothy_hpc_... exactly once; it is valid for terminal.pairing_code_ttl (24, 3.2). Needs step-up. The code is a one-time secret: a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret instead of repeating it (06, 7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: HostCreate
Request
{
"name": "Build server",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"reason": "Shared build machine for Alex"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: HostPairingCode |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"pairing_code": "bothy_hpc_EXAMPLE000000000000000000000000000000000000_EXAMPL",
"expires_at": "2026-10-10T09:45:00.000Z"
}
pairHost¶
POST /hosts/pair
Redeem a pairing code from the host service
Called by bothy-host pair without login. Registers the static X25519 key (Noise) and the Ed25519 key (login) of the host, its profiles and the names of its session users (reported_session_users, 24 section 2.2). The host becomes confirming, key_generation rises; an owner confirms the fingerprint (24, 3.2). Every code that does not work answers 401 unauthenticated with the same body: a wrong form or checksum (checked without database access), an unknown, used, replaced or expired code; a retry after a lost answer gets 401 too, the operator asks for a new code. Key rules (400 validation_failed, the code stays valid): noise_public_key strict base64url of 32 bytes and no low-order point (errors[].code invalid_key); auth_public_jwk exactly kty OKP, crv Ed25519 and x of 32 bytes (invalid_key), any other member such as the private d is unknown_member. Report rules: at least one session user (empty), names distinct without regard to case (duplicate) and at most host.os_user_max_chars characters (too_long), labels and profile names at most terminal.report_label_max_chars characters (too_long), each list at most terminal.report_max_entries entries (limit_reached), distinct profile names (duplicate), host_version SemVer without v (invalid_format). 409 conflict with reason host_key_in_use when the login key belongs to another host, host_key_reused when the keys equal the keys a re-pairing dropped; the code stays valid.
- Security: none
x-authz-action:host.pairx-rate-limit-class:rl.public_authx-idempotency-exempt:auth_flow
Request body (required): application/json: HostPairRequest
Request
{
"pairing_code": "bothy_hpc_EXAMPLE000000000000000000000000000000000000_EXAMPL",
"noise_public_key": "Zm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyMTI",
"auth_public_jwk": {
"kty": "OKP",
"crv": "Ed25519",
"x": "EXAMPLE-ed25519-public-key-base64url-0000000"
},
"platform": "linux",
"os_version": "Debian 13",
"host_version": "1.0.0",
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
]
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: HostPairResult |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"instance_id": "0192f4a0-7b1c-7000-8a00-000000000001"
}
getHost¶
GET /hosts/{host_id}
Read a host
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.readx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Host |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
updateHost¶
PATCH /hosts/{host_id}
Change name or assignee of a host
A new assigned_user_id ends the sessions of people who no longer qualify under SR10 (access_revoked). add_session_users assigns own session users (ruling T12; a taken name gives 409 conflict with reason: session_user_taken, a name the host does not report in reported_session_users gives 400 validation_failed with errors[].code session_user_not_on_host); revoke_session_users ends the assignment of the listed people, ends their sessions on the host (access_revoked) and keeps the name taken (24 section 2.2). Needs step-up.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: HostUpdate
Request
{
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"reason": "Robin hands the machine to Alex"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Host |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
issueHostPairingCode¶
POST /hosts/{host_id}/pairing-code
Issue a new pairing code (re-pairing)
Sets the host to pairing from pairing, confirming, active or disabled (also duplicate_connection, whose reason is cleared); retired gives 409 invalid_state_transition. From confirming, active and disabled it drops the stored keys at once; from active it ends the sessions (host_rekeyed) and closes the connections. Every owner gets host.updated, with key_changed exactly when stored keys were dropped (24, 3.3); key_generation rises at the next pairHost. A repeated call issues another code and invalidates the previous one. Needs step-up. The code is a one-time secret: a replay with the same Idempotency-Key answers 409 conflict with reason one_time_secret instead of repeating it (06, 7).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Host reinstalled"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: HostPairingCode |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 422 | UnprocessableEntity: Problem codes: idempotency_key_reuse. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"pairing_code": "bothy_hpc_EXAMPLE000000000000000000000000000000000000_EXAMPL",
"expires_at": "2026-10-10T09:45:00.000Z"
}
confirmHost¶
POST /hosts/{host_id}/confirm
Confirm the fingerprint and declare the LLM login
The owner types the first terminal.fingerprint_confirm_chars characters shown by bothy-host pair, without separators, case-insensitive; a prefix of another length or with a character outside the Crockford alphabet (also I, L, O, U) gives 400 validation_failed with errors[].code invalid_format and does not count. A mismatch gives 409 fingerprint_mismatch with attempts_remaining; the failure counter is not part of Host, so version and the If-Match stay. After terminal.fingerprint_max_attempts failures the host falls back to pairing without keys (attempts_remaining 0), and a new pairing code is needed. A failed attempt counts also under an Idempotency-Key; its replay returns the stored 409. I6 is checked in the same transaction (409 i6_violation). session_users assigns each person their own session user on this host (ruling T12, 24 section 2.2); a name that belongs or belonged to another person on this host, or a second valid assignment of one person, gives 409 conflict with reason: session_user_taken; a name the host did not report (reported_session_users) gives 400 validation_failed with errors[].code session_user_not_on_host, and nothing is stored. Without an assignment a person gets no terminal there (SR12). Needs step-up.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: HostConfirm
Request
{
"fingerprint_prefix": "7K2QM9XD",
"llm_credentials": "organization",
"declared_server_host": false,
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin"
}
],
"reason": "Build machine of the engineering team"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Host |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
setHostLlmCredentials¶
PUT /hosts/{host_id}/llm-credentials
Declare the LLM login of a host
personal needs credential_holder_id, a person that is not deleted; none and organization take none. Fails with 409 i6_violation (member conflicts, one entry per host) if any valid grant on the host names another subject than the holder or a group; switching to personal or changing the holder ends the sessions of other people in the same transaction (close_reason i6_violation, 24, 7.3). A retired host answers 409 conflict. The declaration the host already has answers 200 with the current host, without a new version, an event or a new rights version (audited with no_change). Needs step-up and the mandatory reason.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes | |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: HostLlmCredentialsSet
Request
{
"llm_credentials": "personal",
"credential_holder_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"reason": "Alex uses the own subscription on this laptop"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Host |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
setHostState¶
POST /hosts/{host_id}/state
Disable, enable or retire a host
disabled and retired end all sessions (host_disabled, host_retired) and close the connections of the host service. retired is final. Needs step-up.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:host.managex-rate-limit-class:rl.admin
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
If-Match |
header | string | yes | ETag of the version the change is based on, e.g. "7". Mismatch gives 412 version_conflict. Example: "7". |
Request body (required): application/json: HostStateSet
Request
{
"state": "disabled",
"reason": "Machine sent for repair"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: Host |
Correlation-Id, RateLimit, RateLimit-Policy, ETag |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 412 | PreconditionFailed: Problem codes: version_conflict. |
application/problem+json: Problem |
Correlation-Id |
| 428 | PreconditionRequired: Problem codes: precondition_required. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"name": "Build server",
"state": "active",
"platform": "linux",
"assigned_user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"llm_credentials": "organization",
"declared_server_host": false,
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"profiles": [
{
"name": "shell",
"display_name": "Shell",
"kind": "shell"
},
{
"name": "claude",
"display_name": "Claude Code",
"kind": "claude"
}
],
"doctor": [
{
"check": "hd1_user",
"ok": true
}
],
"session_users": [
{
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"os_user": "bothy-s-robin",
"created_at": "2026-10-10T09:42:00.000Z"
}
],
"reported_session_users": [
{
"os_user": "bothy-s-robin",
"workdirs": [
"Project A"
]
}
],
"connected": true,
"host_version": "1.0.0",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
Terminal¶
Terminal sessions on connected hosts; the stream itself is end-to-end encrypted and runs over the channels in asyncapi.yaml.
openTerminalSession¶
POST /hosts/{host_id}/terminal/sessions
Open a terminal session
Needs a fresh, unused step-up (passkey or step-up device key; in the console only a passkey with userVerification = required), the terminal capability, SR10, SR11 (I6) and SR12 (an own session user on the host whose name the host reports, otherwise 403 terminal_denied with reason: no_session_user). With a claude profile workdir_index must point into the caller's own working directories (ruling T13). Consumes the step-up and returns a one-time session token for the Noise handshake (24, 5 and 6.1). The device then connects to stream_path.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:terminal.openx-rate-limit-class:rl.terminalx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
host_id |
path | Uuid | yes |
Request body (required): application/json: TerminalSessionOpen
Request
{
"profile": "shell",
"cols": 120,
"rows": 40,
"client_ephemeral_key_hash": "EXAMPLE-sha256-of-ephemeral-key-base64url00"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 201 | Created. | application/json: TerminalSessionGrant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"session": {
"id": "0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f",
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"profile": "shell",
"state": "active",
"opened_at": "2026-10-10T09:31:00.000Z",
"started_at": "2026-10-10T09:31:01.000Z",
"bytes_in": 4096,
"bytes_out": 65536,
"version": 2
},
"session_token": "eyJhbGciOiJFZERTQSIsImtpZCI6InRlcm0tMjAyNi0xMCIsInR5cCI6InRlcm1pbmFsLXNlc3Npb24rand0In0.EXAMPLE.EXAMPLE",
"session_token_expires_at": "2026-10-10T09:31:30.000Z",
"stream_path": "/api/v1/terminal/sessions/0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f/stream",
"noise_public_key": "Zm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyMTI",
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"noise_protocol": "Noise_NK_25519_ChaChaPoly_SHA256",
"prologue_version": "bothy-terminal/1"
}
listTerminalSessions¶
GET /terminal/sessions
List terminal sessions
Own sessions; owners see all sessions. Metadata only, never content.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:terminal.read_ownx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
cursor |
query | Cursor | no | Cursor from next_cursor of the previous page. |
limit |
query | PageLimit | no | |
host_id |
query | Uuid | no | Only sessions on this host. |
state |
query | TerminalSessionState | no | Only sessions in this state; without it, all states. |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TerminalSessionPage |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"items": [
{
"id": "0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f",
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"profile": "shell",
"state": "active",
"opened_at": "2026-10-10T09:31:00.000Z",
"started_at": "2026-10-10T09:31:01.000Z",
"bytes_in": 4096,
"bytes_out": 65536,
"version": 2
}
]
}
getTerminalSession¶
GET /terminal/sessions/{session_id}
Read a terminal session
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:terminal.read_ownx-rate-limit-class:rl.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
session_id |
path | Uuid | yes |
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TerminalSession |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f",
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"profile": "shell",
"state": "active",
"opened_at": "2026-10-10T09:31:00.000Z",
"started_at": "2026-10-10T09:31:01.000Z",
"bytes_in": 4096,
"bytes_out": 65536,
"version": 2
}
attachTerminalSession¶
POST /terminal/sessions/{session_id}/attach
Attach to an own session again
For a session in state opening, active or detached. Needs a fresh step-up, except from the same device in the same login session within terminal.quick_reattach_window after the disconnect. Returns a new session token; older tokens become worthless. A connection of another device is closed with 4103 (24, 6.2). An attach to an opening session restarts the opening (att = open, new deadline).
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:terminal.attachx-rate-limit-class:rl.terminalx-idempotency-exempt:auth_flow
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
session_id |
path | Uuid | yes |
Request body (required): application/json: TerminalSessionAttach
Request
{
"cols": 120,
"rows": 40,
"client_ephemeral_key_hash": "EXAMPLE-sha256-of-ephemeral-key-base64url00"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TerminalSessionGrant |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"session": {
"id": "0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f",
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"profile": "shell",
"state": "active",
"opened_at": "2026-10-10T09:31:00.000Z",
"started_at": "2026-10-10T09:31:01.000Z",
"bytes_in": 4096,
"bytes_out": 65536,
"version": 2
},
"session_token": "eyJhbGciOiJFZERTQSIsImtpZCI6InRlcm0tMjAyNi0xMCIsInR5cCI6InRlcm1pbmFsLXNlc3Npb24rand0In0.EXAMPLE.EXAMPLE",
"session_token_expires_at": "2026-10-10T09:31:30.000Z",
"stream_path": "/api/v1/terminal/sessions/0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f/stream",
"noise_public_key": "Zm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyZm9vYmFyMTI",
"key_fingerprint": "7K2Q-M9XD-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000-0000",
"key_generation": 1,
"noise_protocol": "Noise_NK_25519_ChaChaPoly_SHA256",
"prologue_version": "bothy-terminal/1"
}
closeTerminalSession¶
POST /terminal/sessions/{session_id}/close
End a terminal session
Own sessions; owners any session (closed_by_owner). The server closes both connections and tells the host service to end the PTY.
- Security: dpopAuth or bearerAuth or consoleSession (default)
x-authz-action:terminal.closex-rate-limit-class:rl.write
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
session_id |
path | Uuid | yes | |
Idempotency-Key |
header | Uuid | no | UUIDv7 chosen by the client per logical operation. A repeat with the same request returns the stored response; a different request gives 422 idempotency_key_reuse; a repeat while the first is running gives 409 request_in_progress. Kept for sync.idempotency_key_ttl. |
Request body (required): application/json: ReasonBody
Request
{
"reason": "Done"
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 200 | OK. | application/json: TerminalSession |
Correlation-Id, RateLimit, RateLimit-Policy |
| 400 | BadRequest: Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed. |
application/problem+json: Problem |
Correlation-Id |
| 401 | Unauthorized: Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof. |
application/problem+json: Problem |
Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce |
| 403 | Forbidden: Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied. |
application/problem+json: Problem |
Correlation-Id |
| 404 | NotFound: Problem codes: not_found. |
application/problem+json: Problem |
Correlation-Id |
| 409 | Conflict: Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch. |
application/problem+json: Problem |
Correlation-Id |
| 429 | TooManyRequests: Problem codes: rate_limited. |
application/problem+json: Problem |
Correlation-Id, Retry-After, RateLimit, RateLimit-Policy |
| default | Error: Any other error, e.g. internal_error (500). |
application/problem+json: Problem |
Correlation-Id |
Response
{
"id": "0192f4a0-7b1c-7b22-9d4f-5a6b7c8d9e0f",
"host_id": "0192f4a0-7b1c-7a11-8c3e-4f5a6b7c8d9e",
"user_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"device_id": "0192f4a0-7b1c-7848-8501-1716705c7dbe",
"profile": "shell",
"state": "closed",
"opened_at": "2026-10-10T09:31:00.000Z",
"started_at": "2026-10-10T09:31:01.000Z",
"bytes_in": 4096,
"bytes_out": 65536,
"version": 2,
"closed_at": "2026-10-10T10:00:00.000Z",
"close_reason": "client_closed"
}
Webhook events¶
Requests the server sends to subscribed endpoints. Delivery, the signature headers, retries and the receiver checks: webhooks; the envelope fields are those of the event schemas below.
onMessageCreatedEvent¶
POST webhook message.created
Event message.created
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:message.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: MessageCreatedEvent
message.created
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "message.created",
"payload": {
"message": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onMessageUpdatedEvent¶
POST webhook message.updated
Event message.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:message.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: MessageUpdatedEvent
message.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "message.updated",
"payload": {
"message": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_seq": 42,
"author": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"client_msg_id": "0192f4a0-7b1c-7f4e-8959-c3574b6ad93b",
"origin": "human",
"kind": "text",
"content_md": "@support-agent the invoice export fails since this morning.",
"content_format": 1,
"silent": false,
"attachments": [
{
"position": 1,
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
],
"mention_ids": [
"0192f4a0-7b1c-718f-86e7-9cb8b914b848"
],
"reactions": [
{
"emoji": "👍",
"count": 3
}
],
"pinned": false,
"components": [
{
"id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"custom_id": "approve-refund",
"type": "button",
"definition": {},
"position": 1,
"single_use": true,
"restricted_to": "any",
"state": "active",
"version": 3
}
],
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onMessageDeletedEvent¶
POST webhook message.deleted
Event message.deleted
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:message.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: MessageDeletedEvent
message.deleted
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"version": 4
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "message.deleted",
"payload": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"thread_seq": 5301,
"deleted_at": "2026-10-10T09:30:00.000Z"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onReactionAddedEvent¶
POST webhook reaction.added
Event reaction.added
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:message.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ReactionAddedEvent
reaction.added
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "reaction.added",
"payload": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"emoji": "👍",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"count": 1
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onReactionRemovedEvent¶
POST webhook reaction.removed
Event reaction.removed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:message.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ReactionRemovedEvent
reaction.removed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "reaction.removed",
"payload": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"emoji": "👍",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"count": 1
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onPinAddedEvent¶
POST webhook pin.added
Event pin.added
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: PinAddedEvent
pin.added
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "pin.added",
"payload": {
"pin": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"pinned_by": "0192f4a0-7b1c-72de-8fae-dfbd3e36ff9a",
"pinned_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onPinRemovedEvent¶
POST webhook pin.removed
Event pin.removed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: PinRemovedEvent
pin.removed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "message",
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "pin.removed",
"payload": {
"pin": {
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"pinned_by": "0192f4a0-7b1c-72de-8fae-dfbd3e36ff9a",
"pinned_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadCreatedEvent¶
POST webhook thread.created
Event thread.created
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadCreatedEvent
thread.created
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.created",
"payload": {
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadUpdatedEvent¶
POST webhook thread.updated
Event thread.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadUpdatedEvent
thread.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.updated",
"payload": {
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadClosedEvent¶
POST webhook thread.closed
Event thread.closed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadClosedEvent
thread.closed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.closed",
"payload": {
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadReopenedEvent¶
POST webhook thread.reopened
Event thread.reopened
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadReopenedEvent
thread.reopened
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.reopened",
"payload": {
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"tag_ids": [
"0192f4a0-7b1c-712d-8017-1dad64203598"
]
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadMovedEvent¶
POST webhook thread.moved
Event thread.moved
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadMovedEvent
thread.moved
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.moved",
"payload": {
"thread": {
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "thread",
"title": "Invoice export fails",
"title_source": "auto",
"state": "open",
"last_message_seq": 5301,
"last_activity_at": "2026-10-10T09:30:00.000Z",
"message_count": 1,
"created_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3,
"moved_at": "2026-10-10T09:30:00.000Z",
"tag_ids": []
},
"from_channel_id": "0192f4a0-7b1c-745e-8621-aacfb6cd0aad"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onThreadMovedOutEvent¶
POST webhook thread.moved_out
Event thread.moved_out
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:channel.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ThreadMovedOutEvent
thread.moved_out
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "channel",
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "thread.moved_out",
"payload": {
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onAgentSessionChangedEvent¶
POST webhook agent_session.changed
Event agent_session.changed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:thread.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AgentSessionChangedEvent
agent_session.changed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "thread",
"id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "agent_session.changed",
"payload": {
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_session": {
"id": "0192f4a0-7b1c-741b-8617-885056753dc0",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"is_current": true,
"started": true,
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"created_at": "2026-10-10T09:30:00.000Z",
"version": 3
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onRunStateChangedEvent¶
POST webhook run.state_changed
Event run.state_changed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:run.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: RunStateChangedEvent
run.state_changed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "run",
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "run.state_changed",
"payload": {
"run": {
"id": "0192f4a0-7b1c-767f-8292-c1b14d7d40df",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"agent_id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"triggered_by": "0192f4a0-7b1c-7db7-8afc-99f48568ad99",
"state": "queued",
"version": 3,
"billing_mode_expected": "personal",
"cost": {
"amount_micros": 1250000,
"currency": "USD",
"is_estimate": true
},
"step_count": 1,
"queued_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onSpaceCreatedEvent¶
POST webhook space.created
Event space.created
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:space.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: SpaceCreatedEvent
space.created
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14"
},
"resource": {
"kind": "space",
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "space.created",
"payload": {
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onSpaceUpdatedEvent¶
POST webhook space.updated
Event space.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:space.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: SpaceUpdatedEvent
space.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14"
},
"resource": {
"kind": "space",
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "space.updated",
"payload": {
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onSpaceArchivedEvent¶
POST webhook space.archived
Event space.archived
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:space.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: SpaceArchivedEvent
space.archived
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14"
},
"resource": {
"kind": "space",
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "space.archived",
"payload": {
"space": {
"id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"name": "Support",
"sort_key": "a0",
"version": 3,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onChannelCreatedEvent¶
POST webhook channel.created
Event channel.created
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:channel.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ChannelCreatedEvent
channel.created
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "channel",
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "channel.created",
"payload": {
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onChannelUpdatedEvent¶
POST webhook channel.updated
Event channel.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:channel.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ChannelUpdatedEvent
channel.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "channel",
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "channel.updated",
"payload": {
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onChannelSettingsChangedEvent¶
POST webhook channel.settings_changed
Event channel.settings_changed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:channel.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ChannelSettingsChangedEvent
channel.settings_changed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "channel",
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "channel.settings_changed",
"payload": {
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"settings_version": 1
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onChannelArchivedEvent¶
POST webhook channel.archived
Event channel.archived
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:channel.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: ChannelArchivedEvent
channel.archived
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "channel",
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "channel.archived",
"payload": {
"channel": {
"id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"kind": "text",
"name": "tickets",
"topic": "Customer tickets",
"sort_key": "a1",
"read_only": false,
"operator": {
"mode": "inherit"
},
"version": 3,
"settings_version": 1,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onCommandChangedEvent¶
POST webhook command.changed
Event command.changed
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:command.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: CommandChangedEvent
command.changed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "command",
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "command.changed",
"payload": {
"command": {
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"owner_principal_id": "0192f4a0-7b1c-7176-8de0-ddf186d11091",
"name": "escalate",
"description": "Escalate the ticket to second level",
"scope_kind": "instance",
"options": [
{
"name": "ticket",
"description": "Ticket number",
"type": "string",
"required": true
}
],
"required_level": "write",
"control": false,
"version": 3
},
"change": "registered"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onFileUpdatedEvent¶
POST webhook file.updated
Event file.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:file.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: FileUpdatedEvent
file.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "file",
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "file.updated",
"payload": {
"file": {
"id": "0192f4a0-7b1c-75c7-88f6-199cc394b56a",
"size_bytes": 48213,
"mime_type": "image/png",
"original_name": "screenshot.png",
"uploaded_by": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"purpose": "attachment",
"upload_state": "complete",
"scan_status": "clean",
"transcript_status": "none",
"thumbnails": [
{
"variant": "small",
"mime_type": "image/jpeg",
"width": 320,
"height": 180
}
],
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onUserUpdatedEvent¶
POST webhook user.updated
Event user.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:user.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: UserUpdatedEvent
user.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "user",
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "user.updated",
"payload": {
"user": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"handle": "sam",
"display_name": "Sam",
"status": "active",
"is_owner": false,
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onAgentUpdatedEvent¶
POST webhook agent.updated
Event agent.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AgentUpdatedEvent
agent.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "agent",
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"version": 3
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "agent.updated",
"payload": {
"agent": {
"id": "0192f4a0-7b1c-7d07-84b0-358556a08a99",
"handle": "support-agent",
"display_name": "Support Agent",
"status": "active",
"adapter_kind": "hermes",
"tool_class": "chat",
"description": "Answers support tickets",
"billing_mode": "personal",
"presence": {
"state": "unknown"
},
"operator_config": {},
"version": 3
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onInstanceUpdatedEvent¶
POST webhook instance.updated
Event instance.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:instance.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: InstanceUpdatedEvent
instance.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "instance"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "instance.updated",
"payload": {
"changed_keys": [
"branding.product_name"
]
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onStatusUpdatedEvent¶
POST webhook status.updated
Event status.updated
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:status.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: StatusUpdatedEvent
status.updated
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {},
"resource": {
"kind": "instance"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "status.updated",
"payload": {
"overall_state": "operational"
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onAccessChangedEvent¶
POST webhook access.changed
Event access.changed
Only for the subscribing app itself.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:self
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AccessChangedEvent
access.changed
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"audience": "self",
"scope": {},
"resource": {
"kind": "principal",
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "access.changed",
"payload": {
"permission_version": 418,
"added": [
{
"kind": "space",
"id": "0192f4a0-7b1c-7835-8fba-fdbdfb6d3b85"
}
],
"removed": [
{
"kind": "space",
"id": "0192f4a0-7b1c-7835-8fba-fdbdfb6d3b85"
}
],
"changed": [
{
"kind": "space",
"id": "0192f4a0-7b1c-7835-8fba-fdbdfb6d3b85"
}
]
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onAgentInvocationEvent¶
POST webhook agent.invocation
Event agent.invocation
Only for webhook subscriptions of the agent itself (webhook as agent transport, docs/spec/04-sync-protocol.md section 15.6). Carries a freshly issued invocation token in the delivery fields.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.events.consume
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AgentInvocationEvent
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status acknowledges every event up to this seq. |
||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries this event with backoff and sends nothing newer before it succeeds. |
onAgentFollowupEvent¶
POST webhook agent.followup
Event agent.followup
Only for webhook subscriptions of the agent itself (webhook as agent transport, docs/spec/04-sync-protocol.md section 15.6). Carries a freshly issued invocation token in the delivery fields.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.events.consume
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AgentFollowupEvent
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status acknowledges every event up to this seq. |
||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries this event with backoff and sends nothing newer before it succeeds. |
onRunCancelRequestedEvent¶
POST webhook run.cancel_requested
Event run.cancel_requested
Only for webhook subscriptions of the agent itself (webhook as agent transport, docs/spec/04-sync-protocol.md section 15.6). Carries a freshly issued invocation token in the delivery fields.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.events.consume
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: RunCancelRequestedEvent
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status acknowledges every event up to this seq. |
||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries this event with backoff and sends nothing newer before it succeeds. |
onAgentConfigChangedEvent¶
POST webhook agent.config_changed
Event agent.config_changed
Only for webhook subscriptions of the agent itself (webhook as agent transport, docs/spec/04-sync-protocol.md section 15.6). Carries a freshly issued invocation token in the delivery fields.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.config.read
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: AgentConfigChangedEvent
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status acknowledges every event up to this seq. |
||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries this event with backoff and sends nothing newer before it succeeds. |
onInteractionCreatedEvent¶
POST webhook interaction.created
Event interaction.created
Only for the subscribing app itself.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.events.consume
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: InteractionCreatedEvent
interaction.created
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"thread_id": "0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
},
"resource": {
"kind": "interaction",
"id": "0192f4a0-7b1c-77f5-8fe4-151103a7b8b5"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "interaction.created",
"payload": {
"interaction": {
"id": "0192f4a0-7b1c-77f5-8fe4-151103a7b8b5",
"component_id": "0192f4a0-7b1c-7080-8a1e-eb7183f5a9a2",
"message_id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"principal_id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"client_interaction_id": "0192f4a0-7b1c-704d-8f46-22a420803f92",
"values": {},
"state": "received",
"created_at": "2026-10-10T09:30:00.000Z"
}
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
onCommandInvokedEvent¶
POST webhook command.invoked
Event command.invoked
Only for the subscribing app itself.
- Security: none
x-authz-action:webhook_out.deliverx-rate-limit-class:nonex-receive-action:agent.events.consume
Parameters:
| Name | In | Type | Required | Description |
|---|---|---|---|---|
webhook-id |
header | Uuid | yes | Event ID; stable across retries, use it to deduplicate. |
webhook-timestamp |
header | integer (int64) | yes | Unix seconds of this attempt. Reject values outside webhook.receiver_tolerance. |
webhook-signature |
header | string | yes | Space-separated signatures v1a,<base64> (Ed25519) and, if enabled, v1,<base64> (HMAC-SHA256) over {webhook-id}.{webhook-timestamp}.{body}. |
Request body (required): application/json: CommandInvokedEvent
command.invoked
{
"id": "0192f4a0-7b1c-7ff0-88b6-7d3b051173dd",
"seq": 5301,
"schema_version": 1,
"occurred_at": "2026-10-10T09:30:00.000Z",
"permission_version": 418,
"scope": {
"space_id": "0192f4a0-7b1c-7881-8522-0a58634abc14",
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203"
},
"resource": {
"kind": "command",
"id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa"
},
"sync_epoch": "0192f4a0-7b1c-7a3e-8c41-5d2e9b7f1a60",
"type": "command.invoked",
"payload": {
"invocation_id": "0192f4a0-7b1c-712e-8ccb-17c85f8d11c9",
"command_id": "0192f4a0-7b1c-7beb-80fc-f336f4fe79aa",
"command_name": "escalate",
"control": false,
"channel_id": "0192f4a0-7b1c-72d4-8bae-7661d2b2f203",
"invoked_by": {
"id": "0192f4a0-7b1c-7f89-8d6b-6960453241bc",
"kind": "user",
"handle": "alex",
"display_name": "Alex"
},
"options": [
{
"name": "ticket",
"value": "4711"
}
]
}
}
Responses:
| Status | Description | Content | Headers |
|---|---|---|---|
| 204 | Accepted. Any 2xx status counts as success. | ||
| 410 | The receiver gave up the endpoint; the server disables the subscription. | ||
| 429 | The server slows down and honors Retry-After; same for 502, 503 and 504. |
||
| default | Failure; the server retries with backoff (docs/api/webhooks.md). |
Security schemes¶
dpopAuth¶
type:httpscheme:DPoP
Access token of a person, bound to the device key (RFC 9449). Send Authorization: DPoP <token>
and a DPoP proof header with htm, htu, iat, jti, ath and the latest server nonce.
Also used by API tokens that were created with dpop_jkt. Inside a run an agent also sends
the header Invocation-Token (#/components/parameters/InvocationToken, 07 guard rule SR9).
bearerAuth¶
type:httpscheme:bearer
API token of an agent, app or personal tool without key binding (Authorization: Bearer <token>). On postIncomingWebhookWithBearer only, the token of an incoming webhook
(bothy_whi_...) instead. Inside a run an agent also sends the header Invocation-Token
(#/components/parameters/InvocationToken, 07 guard rule SR9).
consoleSession¶
type:apiKeyin:cookiename:__Host-console_session
Web console cookie; CSRF header ConsoleRequest and own Origin on writes (08, 7.5).
fileTicket¶
type:apiKeyin:queryname:ticket
Short-lived fetch ticket from createFileTicket for media players that cannot send a DPoP
proof (12, 9.2; ADR 0048). Only downloadFile and downloadThumbnail accept it; every fetch
checks signature, expiry, session and file.read, and any failure gives 404.
pushPreviewToken¶
type:httpscheme:DPoP
Preview token of a push registration (bothy_pvw_..., issued once by registerPush) with a DPoP proof of the device key of the registration's session, ath over the preview token (13, 6.4; R-PN-07). Only getPushPreview accepts it; it has no refresh and ends with its registration, its session, its device or its person.
Shared responses¶
BadRequest¶
Problem codes: validation_failed, malformed_request, cursor_invalid, webhook_host_not_allowed.
x-status:400
Content: application/problem+json: Problem
Headers: Correlation-Id
Validation failed
{
"type": "/api/v1/problems/validation_failed",
"title": "Validation failed",
"status": 400,
"code": "validation_failed",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"errors": [
{
"pointer": "/content_md",
"code": "too_long",
"detail": "Longer than `message.max_content_bytes`."
}
]
}
ConsoleLogin¶
Console session (08, 7.5).
x-status:200
Content: application/json: ConsoleSession
Headers: Correlation-Id, Set-Cookie
StepUpDone¶
OK; a console session gets a new cookie (08, 7.5).
x-status:200
Content: application/json: StepUpResult
Headers: Correlation-Id, Set-Cookie
Unauthorized¶
Problem codes: unauthenticated, token_expired, session_revoked, step_up_required, use_dpop_nonce, invalid_dpop_proof.
x-status:401
Content: application/problem+json: Problem
Headers: Correlation-Id, Set-Cookie, WWW-Authenticate, DPoP-Nonce
Unauthenticated
{
"type": "/api/v1/problems/unauthenticated",
"title": "Unauthenticated",
"status": 401,
"code": "unauthenticated",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
Forbidden¶
Problem codes: forbidden, scope_missing, device_pending, channel_read_only, feature_disabled, agent_invocation_denied, invocation_token_invalid, terminal_denied.
x-status:403
Content: application/problem+json: Problem
Headers: Correlation-Id
Forbidden
{
"type": "/api/v1/problems/forbidden",
"title": "Forbidden",
"status": 403,
"code": "forbidden",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
NotFound¶
Problem codes: not_found.
x-status:404
Content: application/problem+json: Problem
Headers: Correlation-Id
Not found
{
"type": "/api/v1/problems/not_found",
"title": "Not found",
"status": 404,
"code": "not_found",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
Conflict¶
Problem codes: conflict, request_in_progress, i1_violation, i6_violation, last_owner, already_started, billing_mode_mismatch, tool_class_mismatch, invalid_state_transition, base_version_conflict, component_used, operator_mismatch, file_not_ready, file_blocked, title_manual, host_unavailable, fingerprint_mismatch.
x-status:409
Content: application/problem+json: Problem
Headers: Correlation-Id
Conflict
{
"type": "/api/v1/problems/conflict",
"title": "Conflict",
"status": 409,
"code": "conflict",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
FileConflict¶
Problem codes: file_not_ready, file_blocked.
x-status:409
Content: application/problem+json: Problem
Headers: Correlation-Id, Retry-After
File not ready
{
"type": "/api/v1/problems/file_not_ready",
"title": "File not ready",
"status": 409,
"code": "file_not_ready",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/files/0192f4a0-7b1c-75c7-88f6-199cc394b56a/content"
}
Gone¶
Problem codes: resync_required, message_deleted, gone.
x-status:410
Content: application/problem+json: Problem
Headers: Correlation-Id
Gone
{
"type": "/api/v1/problems/gone",
"title": "Gone",
"status": 410,
"code": "gone",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
PreconditionFailed¶
Problem codes: version_conflict.
x-status:412
Content: application/problem+json: Problem
Headers: Correlation-Id
Version conflict
{
"type": "/api/v1/problems/version_conflict",
"title": "Version conflict",
"status": 412,
"code": "version_conflict",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d",
"current": {
"id": "0192f4a0-7b1c-7353-8d8c-dea659467151",
"version": 8
}
}
PayloadTooLarge¶
Problem codes: payload_too_large.
x-status:413
Content: application/problem+json: Problem
Headers: Correlation-Id
Payload too large
{
"type": "/api/v1/problems/payload_too_large",
"title": "Payload too large",
"status": 413,
"code": "payload_too_large",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
UnsupportedMediaType¶
Problem codes: unsupported_media_type.
x-status:415
Content: application/problem+json: Problem
Headers: Correlation-Id
Unsupported media type
{
"type": "/api/v1/problems/unsupported_media_type",
"title": "Unsupported media type",
"status": 415,
"code": "unsupported_media_type",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
RangeNotSatisfiable¶
Problem codes: range_not_satisfiable.
x-status:416
Content: application/problem+json: Problem
Headers: Correlation-Id, Content-Range
Range not satisfiable
{
"type": "/api/v1/problems/range_not_satisfiable",
"title": "Range not satisfiable",
"status": 416,
"code": "range_not_satisfiable",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
UnprocessableEntity¶
Problem codes: idempotency_key_reuse.
x-status:422
Content: application/problem+json: Problem
Headers: Correlation-Id
Idempotency key reused
{
"type": "/api/v1/problems/idempotency_key_reuse",
"title": "Idempotency key reused",
"status": 422,
"code": "idempotency_key_reuse",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
PreconditionRequired¶
Problem codes: precondition_required.
x-status:428
Content: application/problem+json: Problem
Headers: Correlation-Id
Precondition required
{
"type": "/api/v1/problems/precondition_required",
"title": "Precondition required",
"status": 428,
"code": "precondition_required",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
TooManyRequests¶
Problem codes: rate_limited.
x-status:429
Content: application/problem+json: Problem
Headers: Correlation-Id, Retry-After, RateLimit, RateLimit-Policy
Too many requests
{
"type": "/api/v1/problems/rate_limited",
"title": "Too many requests",
"status": 429,
"code": "rate_limited",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
ServiceUnavailable¶
Problem codes: unavailable, maintenance, setup_required.
x-status:503
Content: application/problem+json: Problem
Headers: Correlation-Id, Retry-After
Service unavailable
{
"type": "/api/v1/problems/unavailable",
"title": "Service unavailable",
"status": 503,
"code": "unavailable",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
Error¶
Any other error, e.g. internal_error (500).
x-status:500
Content: application/problem+json: Problem
Headers: Correlation-Id
Internal error
{
"type": "/api/v1/problems/internal_error",
"title": "Internal error",
"status": 500,
"code": "internal_error",
"correlation_id": "0192f4a0-7b1c-7577-8bf0-c4f4ee4f887e",
"instance": "/api/v1/threads/0192f4a0-7b1c-78f9-8074-fa94e84bab7d"
}
Shared headers¶
Correlation-Id¶
Type: CorrelationId
Correlation ID of this request (its W3C trace ID written as UUID); also in problem bodies, events and audit entries. Clients never send it.
RateLimit¶
Type: string
Remaining quota of the rate-limit class, format of draft-ietf-httpapi-ratelimit-headers (work in progress), e.g. "rl.message";r=17;t=4.
RateLimit-Policy¶
Type: string
Quota policy of the rate-limit class, e.g. "rl.message";q=60;w=60.
Retry-After¶
Type: integer
Seconds to wait before retrying (RFC 9110).
ETag¶
Type: string
Strong entity tag of the resource version, e.g. "7".
File-ETag¶
Type: string
"<sha256 hex>", the lowercase hex SHA-256 of the whole delivered variant (12, 9.3); not a version.
Repr-Digest¶
Type: string
sha-256=:<base64>: of the whole delivered variant (RFC 9530); the client checks it after the download.
Accept-Ranges¶
Type: string
Always bytes; exactly one range is supported.
Content-Range¶
Type: string
bytes <first>-<last>/<size> with 206, bytes */<size> with 416 (RFC 9110).
Content-Disposition¶
Type: string
inline only for the inline list of 12 9.3, otherwise attachment; always filename="<ASCII fallback>" before filename*=UTF-8''<percent-encoded> (RFC 6266, RFC 8187).
File-Content-Security-Policy¶
Type: string
Always default-src 'none'; sandbox, so an upload never runs as a page of the instance (12, 9.3).
Cross-Origin-Resource-Policy¶
Type: string
Always same-origin.
File-Cache-Control¶
Type: string
private, max-age=<client.cache_max_age>, immutable with normal authentication, private, no-store with a ticket (12, 9.3; ADR 0048).
Idempotent-Replay¶
Type: boolean
true when the response is the stored original of an earlier identical request.
Location¶
Type: string (uri)
Target of the redirect.
Set-Cookie¶
Type: string
Console cookie or its clearing value (08, 7.5).
WWW-Authenticate¶
Type: string
Authentication challenge, e.g. DPoP error="use_dpop_nonce" (RFC 9449).
DPoP-Nonce¶
Type: string
Fresh server nonce for the next DPoP proof (RFC 9449).
Deprecation¶
Type: string
Deprecation date of this operation as structured field date (RFC 9745), e.g. @1798761599. Sent by deprecated operations only.
Sunset¶
Type: string
Date after which the operation stops working (RFC 8594). Not earlier than Deprecation plus api.deprecation_min_notice.
Link¶
Type: string
rel="deprecation" link to the migration notes of a deprecated operation (RFC 9745).