/api/v1

Anticapture API

Use the API to read released documents and releases, check liveness, fetch the OpenAPI document, identify the acting credential, and administer API keys.

Authentication

Send bearer credentials for protected routes.

Released document, release, search, OpenAPI, and health routes are public. Identity and API-key administration require a session cookie or Authorization: Bearer with a key that starts with sk_test_, sk_live_, or rk_.

Key types

sk_test_ and sk_live_ create test and live agent credentials. rk_ creates a restricted credential.

Scopes

API keys carry a role, explicit scopes, and optional resource_constraints. API-key administration requires the admin role and api_keys.write.

Storage

The server stores the key prefix and HMAC hash. Create and rotate responses include the plaintext secret once.

Conventions

Use the response envelope as the contract.

Envelope
Object responses include an object discriminator. Lists use object, url, has_more, next_cursor, and data.
Fields
JSON fields use snake_case. IDs are opaque strings; do not parse them for meaning.
Request IDs
Responses include the Solon-Request-Id header. Error bodies repeat that value as request_id.
Idempotency
Required mutations reject a missing Idempotency-Key. Recommended mutations record and replay a response only when the header is supplied.
58routes
44credentialed routes
26idempotent mutations
17defined scopes
Agent read workflow

Pin reads to released public state.

Current agent-safe API work is read-only against released documents and releases. A credentialed agent should first inspect its role, scopes, and resource constraints, then sync a release package and fetch document blocks or snapshots by ID. Draft, proposal, review, merge, and release-publishing routes are intentionally absent from this production slice.

1. GET /me
Confirm the acting key, role, scopes, and constraints before the run.
2. GET /releases/latest
Pin the run to a published release and its document-version list.
3. GET /documents/{document}/blocks
Fetch stable block IDs and text for citation-aware reading.
4. GET /snapshots/{snapshot}
Fetch immutable content only after resolving it from a released version.
Read sync
curl https://anticapture.localhost/api/v1/me \
  -H "Authorization: Bearer rk_..." \
  -H "Accept: application/json"

curl https://anticapture.localhost/api/v1/releases/latest \
  -H "Accept: application/json"

curl "https://anticapture.localhost/api/v1/documents/doc_0123456789abcdef/blocks?limit=100" \
  -H "Accept: application/json"
Routes

Call the route that matches the job.

Identity1 route
GET/me

Resolve the actor and capabilities behind the credential

Call this before an automation run to confirm the role, scopes, API key ID, and resource constraints that the server will enforce.

Auth
Credentialed
Idempotency
No idempotency record
Operation
retrieveCurrentActor

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl https://anticapture.localhost/api/v1/me \
  -H "Accept: application/json" \
  -H "Authorization: Bearer rk_5f2c1d0e9a8b7c6d_..."
Response JSON
{
  "object": "identity",
  "actor": "key_0123456789abcdef",
  "actor_type": "agent",
  "role": "maintainer",
  "scopes": [
    "releases.read",
    "releases.write"
  ],
  "api_key": "key_0123456789abcdef",
  "resource_constraints": {
    "releases": [
      "rel_2026_07"
    ]
  },
  "api_version": "v1"
}
Documents7 routes
GET/documents

List latest released documents

Build a reading-room index from the current public release without touching workspace drafts or unreleased heads.

Auth
Public
Idempotency
No idempotency record
Operation
listDocuments

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
curl
curl "https://anticapture.localhost/api/v1/documents?limit=25" \
  -H "Accept: application/json"
Response JSON
{
  "object": "list",
  "url": "/documents",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "doc_0123456789abcdef",
      "object": "document",
      "slug": "anti-shell-ownership",
      "title": "Anti-Shell Ownership Act",
      "reform_area": "shell-ownership-and-strategic-assets",
      "doc_type": "statute",
      "visibility": "public",
      "latest_version": null,
      "latest_released_version": "1.0.0",
      "created_at": "2026-07-07T12:00:00.000Z",
      "updated_at": "2026-07-07T12:00:00.000Z"
    }
  ]
}
GET/documents/{document}

Retrieve released document metadata by ID

Resolve title, slug, public visibility, and latest released version before fetching blocks, versions, or snapshots.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveDocument

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/documents/doc_0123456789abcdef \
  -H "Accept: application/json"
Response JSON
{
  "id": "doc_0123456789abcdef",
  "object": "document",
  "slug": "anti-shell-ownership",
  "title": "Anti-Shell Ownership Act",
  "reform_area": "shell-ownership-and-strategic-assets",
  "doc_type": "statute",
  "visibility": "public",
  "latest_version": null,
  "latest_released_version": "1.0.0",
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:00:00.000Z"
}
GET/documents/slug/{slug}

Retrieve released document metadata by slug

Use stable public slugs from the reading room when linking to API-backed document metadata.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveDocumentBySlug

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/documents/slug/anti-shell-ownership \
  -H "Accept: application/json"
Response JSON
{
  "id": "doc_0123456789abcdef",
  "object": "document",
  "slug": "anti-shell-ownership",
  "title": "Anti-Shell Ownership Act",
  "reform_area": "shell-ownership-and-strategic-assets",
  "doc_type": "statute",
  "visibility": "public",
  "latest_version": null,
  "latest_released_version": "1.0.0",
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:00:00.000Z"
}
GET/documents/{document}/blocks

List blocks for the latest released version

Fetch stable block IDs and text anchors for citations, search snippets, and downstream rendering.

Auth
Public
Idempotency
No idempotency record
Operation
listDocumentBlocks

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl "https://anticapture.localhost/api/v1/documents/doc_0123456789abcdef/blocks?limit=25" \
  -H "Accept: application/json"
Response JSON
{
  "object": "list",
  "url": "/documents/doc_0123456789abcdef/blocks",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "blk_0123456789abcdef",
      "object": "block",
      "snapshot": "snap_0123456789abcdef",
      "stable_block_id": "SEC-001",
      "parent_block_id": null,
      "order_index": 0,
      "block_type": "section",
      "citation_label": "SEC. 1.",
      "text": "Short title."
    }
  ]
}
GET/documents/{document}/versions

List released versions for a document

Show public version history that has appeared in a release package.

Auth
Public
Idempotency
No idempotency record
Operation
listDocumentVersions

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl "https://anticapture.localhost/api/v1/documents/doc_0123456789abcdef/versions?limit=25" \
  -H "Accept: application/json"
Response JSON
{
  "object": "list",
  "url": "/documents/doc_0123456789abcdef/versions",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "ver_0123456789abcdef",
      "object": "version",
      "document": "doc_0123456789abcdef",
      "version_label": "1.0.0",
      "commit": "cmt_0123456789abcdef",
      "proposal": null,
      "created_at": "2026-07-07T12:00:00.000Z"
    }
  ]
}
GET/versions/{version}

Retrieve a released document version

Resolve the commit and proposal provenance attached to a released version ID.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveVersion

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/versions/ver_0123456789abcdef \
  -H "Accept: application/json"
Response JSON
{
  "id": "ver_0123456789abcdef",
  "object": "version",
  "document": "doc_0123456789abcdef",
  "version_label": "1.0.0",
  "commit": "cmt_0123456789abcdef",
  "proposal": null,
  "created_at": "2026-07-07T12:00:00.000Z"
}
GET/snapshots/{snapshot}

Retrieve immutable released snapshot content

Fetch the canonical JSON content for a released version after resolving its commit and snapshot.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveSnapshot

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/document_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "document_not_found",
    "message": "No document matches doc_0123456789abcdef.",
    "param": "document",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/document_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/snapshots/snap_0123456789abcdef \
  -H "Accept: application/json"
Response JSON
{
  "id": "snap_0123456789abcdef",
  "object": "snapshot",
  "content_hash": "2f4d8e8d5c1b0a9e6c3a7f1b2d4c6e8f90123456789abcdef0123456789abcd",
  "content_json": {
    "type": "doc",
    "content": []
  },
  "created_at": "2026-07-07T12:00:00.000Z"
}
Diffs0 routes
Releases3 routes
GET/releases

List public releases

Build release history pages and automation that tracks which document versions shipped together.

Auth
Public
Idempotency
No idempotency record
Operation
listReleases

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
curl
curl "https://anticapture.localhost/api/v1/releases?limit=25" \
  -H "Accept: application/json"
Response JSON
{
  "object": "list",
  "url": "/releases",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "rel_0123456789abcdef",
      "object": "release",
      "version_label": "2026.07",
      "title": "July 2026 Public Release",
      "notes": "Initial published reading-room release.",
      "published_by": "usr_0123456789abcdef",
      "published_at": "2026-07-07T12:00:00.000Z",
      "documents": [
        {
          "document": "doc_0123456789abcdef",
          "version": "ver_0123456789abcdef"
        }
      ]
    }
  ]
}
GET/releases/latest

Retrieve the latest public release

Pin a reading-room sync to the newest release package ordered by publication time.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveLatestRelease

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl https://anticapture.localhost/api/v1/releases/latest \
  -H "Accept: application/json"
Response JSON
{
  "id": "rel_0123456789abcdef",
  "object": "release",
  "version_label": "2026.07",
  "title": "July 2026 Public Release",
  "notes": "Initial published reading-room release.",
  "published_by": "usr_0123456789abcdef",
  "published_at": "2026-07-07T12:00:00.000Z",
  "documents": [
    {
      "document": "doc_0123456789abcdef",
      "version": "ver_0123456789abcdef"
    }
  ]
}
GET/releases/{release}

Retrieve a public release by ID

Fetch a specific release package and its document-version membership.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveRelease

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/release_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "release_not_found",
    "message": "No release matches rel_0123456789abcdef.",
    "param": "release",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/release_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/releases/rel_0123456789abcdef \
  -H "Accept: application/json"
Response JSON
{
  "id": "rel_0123456789abcdef",
  "object": "release",
  "version_label": "2026.07",
  "title": "July 2026 Public Release",
  "notes": "Initial published reading-room release.",
  "published_by": "usr_0123456789abcdef",
  "published_at": "2026-07-07T12:00:00.000Z",
  "documents": [
    {
      "document": "doc_0123456789abcdef",
      "version": "ver_0123456789abcdef"
    }
  ]
}
Drafts0 routes
Proposals0 routes
Comments0 routes
Drafter notes0 routes
Members0 routes
Invite requests0 routes
API keys5 routes
GET/api-keys

List API key metadata

Use this for operator audits, key inventory screens, and checks that verify a release or CI key exists before use.

Auth
Credentialed · admin role · api_keys.write
Idempotency
No idempotency record
Operation
listApiKeys

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: api_keys.write.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
403authorization_error/missing_required_role
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_role",
    "message": "The request requires the admin role.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_role"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
curl
curl "https://anticapture.localhost/api/v1/api-keys?limit=25" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..."
Response JSON
{
  "object": "list",
  "url": "/api-keys",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "key_0123456789abcdef",
      "object": "api_key",
      "name": "Release operator",
      "prefix": "rk_5f2c1d0e9a8b7c6d",
      "type": "restricted",
      "role": "maintainer",
      "scopes": [
        "releases.read",
        "releases.write"
      ],
      "resource_constraints": {
        "releases": [
          "rel_2026_07"
        ]
      },
      "created_by": "user_0123456789abcdef",
      "last_used_at": null,
      "expires_at": "2026-12-31T23:59:59.000Z",
      "revoked_at": null,
      "created_at": "2026-07-07T12:00:00.000Z",
      "updated_at": "2026-07-07T12:00:00.000Z"
    }
  ]
}
POST/api-keys

Mint an API key and return the secret once

Create a scoped credential for CI, a release operator, or another automation identity that should not inherit a full user session.

Auth
Credentialed · admin role · api_keys.write
Idempotency
Idempotency-Key required
Operation
createApiKey

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: api_keys.write.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
403authorization_error/missing_required_role
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_role",
    "message": "The request requires the admin role.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_role"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
415invalid_request_error/unsupported_content_type
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_content_type",
    "message": "JSON request bodies require Content-Type: application/json.",
    "param": "Content-Type",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_content_type"
  }
}
400invalid_request_error/malformed_json
{
  "error": {
    "type": "invalid_request_error",
    "code": "malformed_json",
    "message": "The request body is not valid JSON.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/malformed_json"
  }
}
400invalid_request_error/invalid_request_body
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_request_body",
    "message": "$.name is required.",
    "param": "body",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_request_body",
    "state": {
      "issues": [
        "$.name is required"
      ]
    }
  }
}
413invalid_request_error/request_body_too_large
{
  "error": {
    "type": "invalid_request_error",
    "code": "request_body_too_large",
    "message": "The request body exceeds the 1000000 byte limit.",
    "param": "body",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/request_body_too_large"
  }
}
400invalid_request_error/invalid_expires_at
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_expires_at",
    "message": "`expires_at` must be an ISO date-time string or null.",
    "param": "expires_at",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_expires_at"
  }
}
400idempotency_error/missing_idempotency_key
{
  "error": {
    "type": "idempotency_error",
    "code": "missing_idempotency_key",
    "message": "This mutation requires an Idempotency-Key header.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_idempotency_key"
  }
}
409idempotency_error/idempotency_key_conflict
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_conflict",
    "message": "The idempotency key was reused with a different actor, route, or request body.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_conflict"
  }
}
409idempotency_error/idempotency_key_in_use
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_in_use",
    "message": "The idempotency key is already processing.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_in_use"
  }
}
curl
curl https://anticapture.localhost/api/v1/api-keys \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9d2f4e84-7c8b-4c8e-a28a-2f78c2f5c4f1" \
  -d '{
    "name": "Release operator",
    "type": "restricted",
    "role": "maintainer",
    "scopes": ["releases.read", "releases.write"],
    "resource_constraints": { "releases": ["rel_2026_07"] },
    "expires_at": "2026-12-31T23:59:59.000Z"
  }'
Response JSON
{
  "id": "key_0123456789abcdef",
  "object": "api_key",
  "name": "Release operator",
  "prefix": "rk_5f2c1d0e9a8b7c6d",
  "type": "restricted",
  "role": "maintainer",
  "scopes": [
    "releases.read",
    "releases.write"
  ],
  "resource_constraints": {
    "releases": [
      "rel_2026_07"
    ]
  },
  "created_by": "user_0123456789abcdef",
  "last_used_at": null,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "revoked_at": null,
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:00:00.000Z",
  "secret": "rk_5f2c1d0e9a8b7c6d_4a7c..."
}
GET/api-keys/{key}

Retrieve API key metadata by ID

Resolve the stored prefix, role, scopes, constraints, and revocation state for an operator-facing key detail view.

Auth
Credentialed · admin role · api_keys.write
Idempotency
No idempotency record
Operation
retrieveApiKey

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: api_keys.write.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
403authorization_error/missing_required_role
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_role",
    "message": "The request requires the admin role.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_role"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/api_key_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "api_key_not_found",
    "message": "No API key matches that ID.",
    "param": "key",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/api_key_not_found"
  }
}
curl
curl https://anticapture.localhost/api/v1/api-keys/key_0123456789abcdef \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..."
Response JSON
{
  "id": "key_0123456789abcdef",
  "object": "api_key",
  "name": "Release operator",
  "prefix": "rk_5f2c1d0e9a8b7c6d",
  "type": "restricted",
  "role": "maintainer",
  "scopes": [
    "releases.read",
    "releases.write"
  ],
  "resource_constraints": {
    "releases": [
      "rel_2026_07"
    ]
  },
  "created_by": "user_0123456789abcdef",
  "last_used_at": null,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "revoked_at": null,
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:00:00.000Z"
}
POST/api-keys/{key}/rotate

Replace an API key secret and return the new secret once

Rotate a credential after staff turnover, suspected exposure, or a scheduled key rollover without changing the key record ID.

Auth
Credentialed · admin role · api_keys.write
Idempotency
Idempotency-Key required
Operation
rotateApiKey

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: api_keys.write.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
403authorization_error/missing_required_role
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_role",
    "message": "The request requires the admin role.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_role"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/api_key_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "api_key_not_found",
    "message": "No API key matches that ID.",
    "param": "key",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/api_key_not_found"
  }
}
415invalid_request_error/unsupported_content_type
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_content_type",
    "message": "JSON request bodies require Content-Type: application/json.",
    "param": "Content-Type",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_content_type"
  }
}
400invalid_request_error/malformed_json
{
  "error": {
    "type": "invalid_request_error",
    "code": "malformed_json",
    "message": "The request body is not valid JSON.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/malformed_json"
  }
}
413invalid_request_error/request_body_too_large
{
  "error": {
    "type": "invalid_request_error",
    "code": "request_body_too_large",
    "message": "The request body exceeds the 1000000 byte limit.",
    "param": "body",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/request_body_too_large"
  }
}
400idempotency_error/missing_idempotency_key
{
  "error": {
    "type": "idempotency_error",
    "code": "missing_idempotency_key",
    "message": "This mutation requires an Idempotency-Key header.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_idempotency_key"
  }
}
409idempotency_error/idempotency_key_conflict
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_conflict",
    "message": "The idempotency key was reused with a different actor, route, or request body.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_conflict"
  }
}
409idempotency_error/idempotency_key_in_use
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_in_use",
    "message": "The idempotency key is already processing.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_in_use"
  }
}
curl
curl https://anticapture.localhost/api/v1/api-keys/key_0123456789abcdef/rotate \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 3cc4dc4b-9467-4b82-a368-601a80e7f22f" \
  -d '{}'
Response JSON
{
  "id": "key_0123456789abcdef",
  "object": "api_key",
  "name": "Release operator",
  "prefix": "rk_fedcba9876543210",
  "type": "restricted",
  "role": "maintainer",
  "scopes": [
    "releases.read",
    "releases.write"
  ],
  "resource_constraints": {
    "releases": [
      "rel_2026_07"
    ]
  },
  "created_by": "user_0123456789abcdef",
  "last_used_at": null,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "revoked_at": null,
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:05:00.000Z",
  "secret": "rk_fedcba9876543210_e1d2..."
}
DELETE/api-keys/{key}

Revoke an API key

Disable a credential before removing it from CI, operator machines, or any system that should stop authenticating immediately.

Auth
Credentialed · admin role · api_keys.write
Idempotency
Idempotency-Key records replays when supplied
Operation
revokeApiKey

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: api_keys.write.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
403authorization_error/missing_required_role
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_role",
    "message": "The request requires the admin role.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_role"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
404not_found_error/api_key_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "api_key_not_found",
    "message": "No API key matches that ID.",
    "param": "key",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/api_key_not_found"
  }
}
413invalid_request_error/request_body_too_large
{
  "error": {
    "type": "invalid_request_error",
    "code": "request_body_too_large",
    "message": "The request body exceeds the 1000000 byte limit.",
    "param": "body",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/request_body_too_large"
  }
}
409idempotency_error/idempotency_key_conflict
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_conflict",
    "message": "The idempotency key was reused with a different actor, route, or request body.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_conflict"
  }
}
409idempotency_error/idempotency_key_in_use
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_in_use",
    "message": "The idempotency key is already processing.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/idempotency_key_in_use"
  }
}
curl
curl -X DELETE https://anticapture.localhost/api/v1/api-keys/key_0123456789abcdef \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..." \
  -H "Idempotency-Key: 8f2a9f55-cf91-4460-bd52-fbd753ed4f4f"
Response JSON
{
  "id": "key_0123456789abcdef",
  "object": "api_key",
  "name": "Release operator",
  "prefix": "rk_5f2c1d0e9a8b7c6d",
  "type": "restricted",
  "role": "maintainer",
  "scopes": [
    "releases.read",
    "releases.write"
  ],
  "resource_constraints": {
    "releases": [
      "rel_2026_07"
    ]
  },
  "created_by": "user_0123456789abcdef",
  "last_used_at": null,
  "expires_at": "2026-12-31T23:59:59.000Z",
  "revoked_at": "2026-07-07T12:10:00.000Z",
  "created_at": "2026-07-07T12:00:00.000Z",
  "updated_at": "2026-07-07T12:10:00.000Z"
}
Audit2 routes
GET/events

List API audit events

Review API-key creation, rotation, and revocation history by request ID, actor, operation, subject, and status.

Auth
Credentialed · audit.read
Idempotency
No idempotency record
Operation
listAuditEvents

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: audit.read.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
400invalid_request_error/invalid_limit
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_limit",
    "message": "The `limit` parameter must be an integer from 1 to 100.",
    "param": "limit",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_limit"
  }
}
400invalid_request_error/invalid_cursor
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_cursor",
    "message": "Use either `starting_after` or `ending_before`, not both.",
    "param": "starting_after",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_cursor"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl "https://anticapture.localhost/api/v1/events?limit=25" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..."
Response JSON
{
  "object": "list",
  "url": "/events",
  "has_more": false,
  "next_cursor": null,
  "data": [
    {
      "id": "apiaud_0123456789abcdef",
      "object": "event",
      "actor": "ak_0123456789abcdef",
      "subject_type": "api_key",
      "subject": "ak_abcdef0123456789",
      "event_type": "api_key.created",
      "payload": {
        "type": "restricted",
        "role": "maintainer",
        "restricted": true
      },
      "created_at": "2026-07-07T12:00:00.000Z",
      "request_id": "req_0123456789abcdef0123456789abcdef",
      "auth_mode": "api_key",
      "operation_id": "createApiKey",
      "status": 201
    }
  ]
}
GET/events/{event}

Retrieve one API audit event

Trace a specific API mutation from its event ID back to request ID, actor, operation, subject, and stored metadata.

Auth
Credentialed · audit.read
Idempotency
No idempotency record
Operation
retrieveAuditEvent

Error cases

401authentication_error/missing_authentication
{
  "error": {
    "type": "authentication_error",
    "code": "missing_authentication",
    "message": "The request requires a valid Solon credential.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_authentication"
  }
}
403authorization_error/missing_required_scope
{
  "error": {
    "type": "authorization_error",
    "code": "missing_required_scope",
    "message": "The request requires these scopes: audit.read.",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/missing_required_scope"
  }
}
404not_found_error/event_not_found
{
  "error": {
    "type": "not_found_error",
    "code": "event_not_found",
    "message": "No event matches apiaud_0123456789abcdef.",
    "param": "event",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/event_not_found"
  }
}
406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl https://anticapture.localhost/api/v1/events/apiaud_0123456789abcdef \
  -H "Accept: application/json" \
  -H "Authorization: Bearer sk_live_5f2c1d0e9a8b7c6d_..."
Response JSON
{
  "id": "apiaud_0123456789abcdef",
  "object": "event",
  "actor": "ak_0123456789abcdef",
  "subject_type": "api_key",
  "subject": "ak_abcdef0123456789",
  "event_type": "api_key.created",
  "payload": {
    "type": "restricted",
    "role": "maintainer",
    "restricted": true
  },
  "created_at": "2026-07-07T12:00:00.000Z",
  "request_id": "req_0123456789abcdef0123456789abcdef",
  "auth_mode": "api_key",
  "operation_id": "createApiKey",
  "status": 201
}
Discovery2 routes
GET/openapi.json

Fetch the OpenAPI 3.1 document

Use this document to generate clients, inspect route security, and verify request and response schemas in integration tests.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveOpenApi

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl https://anticapture.localhost/api/v1/openapi.json \
  -H "Accept: application/json"
OpenAPI 3.1 documentopenapi.json · 58 routes · v1↓
GET/health

Check API liveness

Wire this endpoint into deploy verification, uptime checks, and smoke tests that need a small JSON response.

Auth
Public
Idempotency
No idempotency record
Operation
retrieveHealth

Error cases

406invalid_request_error/unsupported_accept
{
  "error": {
    "type": "invalid_request_error",
    "code": "unsupported_accept",
    "message": "The API only returns application/json.",
    "param": "Accept",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/unsupported_accept"
  }
}
curl
curl https://anticapture.localhost/api/v1/health \
  -H "Accept: application/json"
Response JSON
{
  "object": "health",
  "api_version": "v1",
  "status": "ok"
}
Errors

Read the typed error body.

Every non-2xx response carries one error object. Branch on type to pick a handling policy and on code for the specific condition. message is for humans and can change without notice.

Fields

type
One of the eight families below. Stable; safe to branch on.
code
The specific condition, stable per route, for example idempotency_key_conflict.
message
Human-readable description. Log it; never parse it.
param
The request field or header at fault, when one can be named.
request_id
Echoes the Solon-Request-Id response header. Include it when reporting a problem.
doc_url
Link to the reference entry for the code.
state
Structured detail when it exists. Validation failures list every failed check under state.issues.
Error body
{
  "error": {
    "type": "invalid_request_error",
    "code": "invalid_request_body",
    "message": "$.name is required.",
    "param": "body",
    "request_id": "req_0123456789abcdef0123456789abcdef",
    "doc_url": "https://docs.solon.dev/errors/invalid_request_body",
    "state": {
      "issues": [
        "$.name is required"
      ]
    }
  }
}

Error types

authentication_error401

No valid credential reached the server. Re-authenticate or supply a bearer key; retrying the same request will fail the same way.

authorization_error403

The credential is valid but lacks the required role, scope, or resource constraint. Fix the key's grants, not the request.

invalid_request_error400 · 406 · 413 · 415

The request itself is wrong: body, parameter, or header. Read param and state.issues, correct the request, then retry.

idempotency_error400 · 409

The Idempotency-Key is missing, was reused with a different payload, or the first attempt is still processing. Use one fresh UUID per logical operation; retry key_in_use only after the original settles.

workflow_state_error409

The resource moved since you read it, usually a stale base or a closed proposal. Refetch current state and reapply the operation.

not_found_error404

Nothing exists at that ID for this credential. Treat unknown and inaccessible identically; do not probe.

rate_limit_error429

Too many requests. Back off and retry with jitter.

api_error500

A server fault. Safe to retry with backoff; report the request_id if it persists.