Docs API reference
Delegations
Delegation of subdomains to other organizations.
5 operations. See the API overview for authentication, errors, idempotency and caching rules that apply to all of them.
List an organization's delegations
GET/v1/delegations
Delegations the organization granted (outgoing) or received (incoming). Any member (or a service token for that
organization). Newest first, at most 200.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
organization_id | query | Yes | OrganizationId |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | Delegations. | application/json DelegationList |
| 400 | invalid_request. Malformed JSON, an invalid or unknown field (see field_errors), a missing or malformed
Idempotency-Key, or a bad query. Also used with status 413 (body over 64 KiB) and 415 (wrong Content-Type). | application/json Error |
| 401 | unauthenticated (no or invalid credentials, or the session has not completed the passkey ceremony) or
step_up_required (the passkey assertion is too old; also returned to service tokens, which can never step up).
Both are 401; tell them apart by code. | application/json Error |
| 404 | not_found. No such resource, or one the caller may not see (the two are indistinguishable by design). | application/json Error |
| 503 | unavailable (temporarily unavailable; also a feature that is not configured in this deployment) or
provider_unavailable (an identity provider is not configured). Both are 503. During maintenance (for example a database
recovery) every mutating request answers unavailable "The directory is under maintenance; try again later." Reads keep working. | application/json Error |
200 example
{
"delegations": [
{
"id": "dlg_2b5d8f1h4k7n0q3s6w9y2a5c8e",
"status": "active",
"status_reason": null,
"version": 3,
"direction": "outgoing",
"parent": {
"organization_id": "org_7k3m9q2x8d5f1h4j6n0p2r4t8v",
"organization_name": "Example Payments, Inc.",
"claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"domain": "payments.example.com"
},
"child_domain": "checkout.payments.example.com",
"recipient": {
"organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"organization_name": "Checkout Partners LLC"
},
"actions": [
"authorize_issuer"
],
"workload_scope": [
"/agent/checkout"
],
"expires_at": "2027-04-05T00:00:00.000Z",
"created_at": "2026-10-05T13:00:00.000Z",
"accepted_at": "2026-10-05T14:00:00.000Z",
"activated_at": "2026-10-05T14:30:00.000Z",
"ended_at": null,
"review": {
"status": "approved"
},
"dependent_bindings": 0,
"next_actions": [
"withdraw"
]
}
]
}
400 example
{
"code": "invalid_request",
"message": "Invalid organization.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"field_errors": [
{
"field": "legal_name",
"message": "must be 1-200 characters"
}
]
}
401 unauthenticated
{
"code": "unauthenticated",
"message": "Sign in required.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
401 step_up_required
{
"code": "step_up_required",
"message": "Recent passkey verification required for this action.",
"request_id": "req_5a8c1f4h7k0m3p6s9v2x5z8b1d"
}
404 example
{
"code": "not_found",
"message": "No such resource.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
503 example
{
"code": "unavailable",
"message": "Temporarily unavailable.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
Delegate a subdomain
POST/v1/delegations
Human only; the parent claim's owner with step-up. Delegates a strict DNS descendant of the parent claim's domain to a
recipient organization, limited to the given actions and workload scope. Creates the delegation pending_review: it activates
when the recipient's owner accepts and one internal reviewer approves (whichever comes second activates it).
The child must already be in the directory (imported, or added with POST /v1/domains): otherwise 422 with
domain_not_in_directory. This route never creates a domain.
Rules, each reported as a field_errors entry whose message is the reason code:
the parent claim must be verified with delegate in its reviewed permitted actions; the child must be a strict descendant
(child_not_strict_descendant); no self-delegation; actions may not include delegate (redelegation_not_supported) and
must be a subset of what the parent holds (action_escalation); the scope must be within the parent's scope
(scope_escalation); expiry must be between 1 minute and 1 year ahead and not after the parent's representative authority
(expiry_beyond_parent); no cycles (delegation_cycle); and no other organization may hold a more specific verified claim
covering the child (child_under_more_specific_claim). Policy refusals are 403 forbidden or 422 semantic_check_failed.
At most 10 delegations per organization per hour (429); a child already pending or active is 409.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
Idempotency-Key | header | Yes | string | Unique key for this logical mutation (1 to 255 characters of A-Z a-z 0-9 . _ : -). Replays within 24 hours return the original outcome.1 to 255 characters; pattern ^[A-Za-z0-9._:-]+$example 7f3c1b52-9d44-4a0e-8f21-0a6e5b9d3c77 |
x-art-csrf | header | Yes | string | The csrf_token from GET /auth/session. Required on every session-authenticated mutation.example Kk3jVq0bYw2p0mT1aZc9sD8eF4gH6iJ7nL5oP2rQ1uA |
Request body
application/json, required: CreateDelegationRequest
| Field | Type | Required | Description |
|---|---|---|---|
parent_claim_id | ClaimId | Yes | |
child_domain | string | Yes | A strict DNS descendant of the parent claim's domain. |
recipient_organization_id | OrganizationId | Yes | |
scope | WorkloadScope | Yes | |
actions | array of one of "authorize_issuer", "manage_domain" | Yes | What the recipient may do. delegate (redelegation) is refused.at least 1 items; unique items |
expires_at | string (date-time) | Yes | ISO 8601 with a time zone; more than 1 minute and at most 1 year ahead, and not after the parent's representative authority. |
Example
{
"parent_claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"child_domain": "checkout.payments.example.com",
"recipient_organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"scope": [
"/agent/checkout"
],
"actions": [
"authorize_issuer"
],
"expires_at": "2027-04-05T00:00:00Z"
}
Responses
| Status | Description | Body |
|---|---|---|
| 201 | The delegation, pending acceptance and review. | application/json DelegationEnvelope |
| 400 | invalid_request. Malformed JSON, an invalid or unknown field (see field_errors), a missing or malformed
Idempotency-Key, or a bad query. Also used with status 413 (body over 64 KiB) and 415 (wrong Content-Type). | application/json Error |
| 401 | unauthenticated (no or invalid credentials, or the session has not completed the passkey ceremony) or
step_up_required (the passkey assertion is too old; also returned to service tokens, which can never step up).
Both are 401; tell them apart by code. | application/json Error |
| 403 | forbidden. Authenticated but not allowed: a role that does not permit the action, a service token on a human-only operation,
a missing or wrong CSRF token, or a request Origin that is not allowed. | application/json Error |
| 404 | not_found. No such resource, or one the caller may not see (the two are indistinguishable by design). | application/json Error |
| 409 | conflict. The record changed since you read it (stale expected_version), the action is not valid in the record's
current state, the Idempotency-Key was reused with a different request, or the same request is still in flight. | application/json Error |
| 422 | semantic_check_failed. The request is well formed but a policy or proof check failed (for example an issuer-control proof
did not verify, a challenge expired, or the organization is not yet verified). field_errors[].message is often a stable
reason code. | application/json Error |
| 429 | rate_limited. A per-client or per-record limit was reached; retry later. | application/json Error |
| 503 | unavailable (temporarily unavailable; also a feature that is not configured in this deployment) or
provider_unavailable (an identity provider is not configured). Both are 503. During maintenance (for example a database
recovery) every mutating request answers unavailable "The directory is under maintenance; try again later." Reads keep working. | application/json Error |
201 example
{
"delegation": {
"id": "dlg_2b5d8f1h4k7n0q3s6w9y2a5c8e",
"status": "pending_review",
"status_reason": null,
"version": 1,
"direction": "outgoing",
"parent": {
"organization_id": "org_7k3m9q2x8d5f1h4j6n0p2r4t8v",
"organization_name": "Example Payments, Inc.",
"claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"domain": "payments.example.com"
},
"child_domain": "checkout.payments.example.com",
"recipient": {
"organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"organization_name": "Checkout Partners LLC"
},
"actions": [
"authorize_issuer"
],
"workload_scope": [
"/agent/checkout"
],
"expires_at": "2027-04-05T00:00:00.000Z",
"created_at": "2026-10-05T13:00:00.000Z",
"accepted_at": null,
"activated_at": null,
"ended_at": null,
"review": {
"status": "pending"
},
"dependent_bindings": 0,
"next_actions": [
"await_recipient_acceptance",
"await_review",
"withdraw"
]
}
}
400 example
{
"code": "invalid_request",
"message": "Invalid organization.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"field_errors": [
{
"field": "legal_name",
"message": "must be 1-200 characters"
}
]
}
401 unauthenticated
{
"code": "unauthenticated",
"message": "Sign in required.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
401 step_up_required
{
"code": "step_up_required",
"message": "Recent passkey verification required for this action.",
"request_id": "req_5a8c1f4h7k0m3p6s9v2x5z8b1d"
}
403 example
{
"code": "forbidden",
"message": "Your role does not permit this action.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
404 example
{
"code": "not_found",
"message": "No such resource.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
409 example
{
"code": "conflict",
"message": "The record changed since you read it; reload and retry with the current version.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
422 example
{
"code": "semantic_check_failed",
"message": "Issuer-control proof failed (endpoint_http_404). 4 attempt(s) left on this challenge.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"field_errors": [
{
"field": "method",
"message": "endpoint_http_404"
}
]
}
429 example
{
"code": "rate_limited",
"message": "Too many requests.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
503 example
{
"code": "unavailable",
"message": "Temporarily unavailable.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
Get a delegation
GET/v1/delegations/{id}
Any member of the parent or the recipient organization (anyone else: 404). A person who belongs to both sees the
parent side.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | Yes | DelegationId | Delegation id. |
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The delegation. | application/json DelegationEnvelope |
| 401 | unauthenticated (no or invalid credentials, or the session has not completed the passkey ceremony) or
step_up_required (the passkey assertion is too old; also returned to service tokens, which can never step up).
Both are 401; tell them apart by code. | application/json Error |
| 404 | not_found. No such resource, or one the caller may not see (the two are indistinguishable by design). | application/json Error |
| 503 | unavailable (temporarily unavailable; also a feature that is not configured in this deployment) or
provider_unavailable (an identity provider is not configured). Both are 503. During maintenance (for example a database
recovery) every mutating request answers unavailable "The directory is under maintenance; try again later." Reads keep working. | application/json Error |
200 example
{
"delegation": {
"id": "dlg_2b5d8f1h4k7n0q3s6w9y2a5c8e",
"status": "active",
"status_reason": null,
"version": 3,
"direction": "incoming",
"parent": {
"organization_id": "org_7k3m9q2x8d5f1h4j6n0p2r4t8v",
"organization_name": "Example Payments, Inc.",
"claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"domain": "payments.example.com"
},
"child_domain": "checkout.payments.example.com",
"recipient": {
"organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"organization_name": "Checkout Partners LLC"
},
"actions": [
"authorize_issuer"
],
"workload_scope": [
"/agent/checkout"
],
"expires_at": "2027-04-05T00:00:00.000Z",
"created_at": "2026-10-05T13:00:00.000Z",
"accepted_at": "2026-10-05T14:00:00.000Z",
"activated_at": "2026-10-05T14:30:00.000Z",
"ended_at": null,
"review": {
"status": "approved"
},
"dependent_bindings": 1,
"next_actions": [
"register_issuers_under_child_domain",
"withdraw"
]
}
}
401 unauthenticated
{
"code": "unauthenticated",
"message": "Sign in required.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
401 step_up_required
{
"code": "step_up_required",
"message": "Recent passkey verification required for this action.",
"request_id": "req_5a8c1f4h7k0m3p6s9v2x5z8b1d"
}
404 example
{
"code": "not_found",
"message": "No such resource.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
503 example
{
"code": "unavailable",
"message": "Temporarily unavailable.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
Accept a delegation
POST/v1/delegations/{id}/accept
Human only; the recipient organization's owner, with step-up. expected_version must equal the delegation's version
(409 otherwise). Activation needs this acceptance AND one internal reviewer approval; whichever comes second activates it.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | Yes | DelegationId | Delegation id. |
Idempotency-Key | header | Yes | string | Unique key for this logical mutation (1 to 255 characters of A-Z a-z 0-9 . _ : -). Replays within 24 hours return the original outcome.1 to 255 characters; pattern ^[A-Za-z0-9._:-]+$example 7f3c1b52-9d44-4a0e-8f21-0a6e5b9d3c77 |
x-art-csrf | header | Yes | string | The csrf_token from GET /auth/session. Required on every session-authenticated mutation.example Kk3jVq0bYw2p0mT1aZc9sD8eF4gH6iJ7nL5oP2rQ1uA |
Request body
application/json, required: ExpectedVersionRequest
| Field | Type | Required | Description |
|---|---|---|---|
expected_version | integer | Yes | The version you last read; a stale value is 409.minimum 1 |
Example
{
"expected_version": 1
}
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The delegation after acceptance (and activation, if review was already done). | application/json DelegationEnvelope |
| 400 | invalid_request. Malformed JSON, an invalid or unknown field (see field_errors), a missing or malformed
Idempotency-Key, or a bad query. Also used with status 413 (body over 64 KiB) and 415 (wrong Content-Type). | application/json Error |
| 401 | unauthenticated (no or invalid credentials, or the session has not completed the passkey ceremony) or
step_up_required (the passkey assertion is too old; also returned to service tokens, which can never step up).
Both are 401; tell them apart by code. | application/json Error |
| 403 | forbidden. Authenticated but not allowed: a role that does not permit the action, a service token on a human-only operation,
a missing or wrong CSRF token, or a request Origin that is not allowed. | application/json Error |
| 404 | not_found. No such resource, or one the caller may not see (the two are indistinguishable by design). | application/json Error |
| 409 | conflict. The record changed since you read it (stale expected_version), the action is not valid in the record's
current state, the Idempotency-Key was reused with a different request, or the same request is still in flight. | application/json Error |
| 503 | unavailable (temporarily unavailable; also a feature that is not configured in this deployment) or
provider_unavailable (an identity provider is not configured). Both are 503. During maintenance (for example a database
recovery) every mutating request answers unavailable "The directory is under maintenance; try again later." Reads keep working. | application/json Error |
200 example
{
"delegation": {
"id": "dlg_2b5d8f1h4k7n0q3s6w9y2a5c8e",
"status": "pending_review",
"status_reason": null,
"version": 2,
"direction": "incoming",
"parent": {
"organization_id": "org_7k3m9q2x8d5f1h4j6n0p2r4t8v",
"organization_name": "Example Payments, Inc.",
"claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"domain": "payments.example.com"
},
"child_domain": "checkout.payments.example.com",
"recipient": {
"organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"organization_name": "Checkout Partners LLC"
},
"actions": [
"authorize_issuer"
],
"workload_scope": [
"/agent/checkout"
],
"expires_at": "2027-04-05T00:00:00.000Z",
"created_at": "2026-10-05T13:00:00.000Z",
"accepted_at": "2026-10-05T14:00:00.000Z",
"activated_at": null,
"ended_at": null,
"review": {
"status": "pending"
},
"dependent_bindings": 0,
"next_actions": [
"await_review",
"withdraw"
]
}
}
400 example
{
"code": "invalid_request",
"message": "Invalid organization.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"field_errors": [
{
"field": "legal_name",
"message": "must be 1-200 characters"
}
]
}
401 unauthenticated
{
"code": "unauthenticated",
"message": "Sign in required.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
401 step_up_required
{
"code": "step_up_required",
"message": "Recent passkey verification required for this action.",
"request_id": "req_5a8c1f4h7k0m3p6s9v2x5z8b1d"
}
403 example
{
"code": "forbidden",
"message": "Your role does not permit this action.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
404 example
{
"code": "not_found",
"message": "No such resource.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
409 example
{
"code": "conflict",
"message": "The record changed since you read it; reload and retry with the current version.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
503 example
{
"code": "unavailable",
"message": "Temporarily unavailable.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
Withdraw a delegation
POST/v1/delegations/{id}/withdraw
Human only; the parent's owner or the recipient's owner, with step-up. In one commit the delegation becomes withdrawn and
every dependent binding leaves service: published ones are suspended (with a public event each), unpublished ones are
withdrawn. A live (pending_review or active) delegation only; expected_version must equal the delegation's version.
Parameters
| Name | In | Required | Type | Description |
|---|---|---|---|---|
id | path | Yes | DelegationId | Delegation id. |
Idempotency-Key | header | Yes | string | Unique key for this logical mutation (1 to 255 characters of A-Z a-z 0-9 . _ : -). Replays within 24 hours return the original outcome.1 to 255 characters; pattern ^[A-Za-z0-9._:-]+$example 7f3c1b52-9d44-4a0e-8f21-0a6e5b9d3c77 |
x-art-csrf | header | Yes | string | The csrf_token from GET /auth/session. Required on every session-authenticated mutation.example Kk3jVq0bYw2p0mT1aZc9sD8eF4gH6iJ7nL5oP2rQ1uA |
Request body
application/json, required: WithdrawRequest
| Field | Type | Required | Description |
|---|---|---|---|
expected_version | integer | Yes | The version you last read; a stale value is 409. |
reason | string | No | Free text (newlines allowed, no other control characters). at most 2000 characters |
Example
{
"expected_version": 3,
"reason": "Partnership ended."
}
Responses
| Status | Description | Body |
|---|---|---|
| 200 | The delegation, now withdrawn. | application/json DelegationEnvelope |
| 400 | invalid_request. Malformed JSON, an invalid or unknown field (see field_errors), a missing or malformed
Idempotency-Key, or a bad query. Also used with status 413 (body over 64 KiB) and 415 (wrong Content-Type). | application/json Error |
| 401 | unauthenticated (no or invalid credentials, or the session has not completed the passkey ceremony) or
step_up_required (the passkey assertion is too old; also returned to service tokens, which can never step up).
Both are 401; tell them apart by code. | application/json Error |
| 403 | forbidden. Authenticated but not allowed: a role that does not permit the action, a service token on a human-only operation,
a missing or wrong CSRF token, or a request Origin that is not allowed. | application/json Error |
| 404 | not_found. No such resource, or one the caller may not see (the two are indistinguishable by design). | application/json Error |
| 409 | conflict. The record changed since you read it (stale expected_version), the action is not valid in the record's
current state, the Idempotency-Key was reused with a different request, or the same request is still in flight. | application/json Error |
| 503 | unavailable (temporarily unavailable; also a feature that is not configured in this deployment) or
provider_unavailable (an identity provider is not configured). Both are 503. During maintenance (for example a database
recovery) every mutating request answers unavailable "The directory is under maintenance; try again later." Reads keep working. | application/json Error |
200 example
{
"delegation": {
"id": "dlg_2b5d8f1h4k7n0q3s6w9y2a5c8e",
"status": "withdrawn",
"status_reason": "withdrawn_by_parent",
"version": 4,
"direction": "outgoing",
"parent": {
"organization_id": "org_7k3m9q2x8d5f1h4j6n0p2r4t8v",
"organization_name": "Example Payments, Inc.",
"claim_id": "clm_4c8e2g6k0m3q7s1w5y9a2d6f8h",
"domain": "payments.example.com"
},
"child_domain": "checkout.payments.example.com",
"recipient": {
"organization_id": "org_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"organization_name": "Checkout Partners LLC"
},
"actions": [
"authorize_issuer"
],
"workload_scope": [
"/agent/checkout"
],
"expires_at": "2027-04-05T00:00:00.000Z",
"created_at": "2026-10-05T13:00:00.000Z",
"accepted_at": "2026-10-05T14:00:00.000Z",
"activated_at": "2026-10-05T14:30:00.000Z",
"ended_at": "2026-11-01T09:00:00.000Z",
"review": {
"status": "approved"
},
"dependent_bindings": 0,
"next_actions": []
}
}
400 example
{
"code": "invalid_request",
"message": "Invalid organization.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w",
"field_errors": [
{
"field": "legal_name",
"message": "must be 1-200 characters"
}
]
}
401 unauthenticated
{
"code": "unauthenticated",
"message": "Sign in required.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
401 step_up_required
{
"code": "step_up_required",
"message": "Recent passkey verification required for this action.",
"request_id": "req_5a8c1f4h7k0m3p6s9v2x5z8b1d"
}
403 example
{
"code": "forbidden",
"message": "Your role does not permit this action.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
404 example
{
"code": "not_found",
"message": "No such resource.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
409 example
{
"code": "conflict",
"message": "The record changed since you read it; reload and retry with the current version.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}
503 example
{
"code": "unavailable",
"message": "Temporarily unavailable.",
"request_id": "req_3m6p9s2v5y8b1e4h7k0n3q6t9w"
}