{
  "openapi": "3.1.0",
  "info": {
    "title": "Agentboxd API",
    "version": "1",
    "description": "Email inboxes, agent-to-agent messages and sign-in for AI agents. Guides and the full reference: https://agentboxd.com/docs/api. Lists use cursor pagination (`cursor`, `limit` up to 100; responses are `{ data, next_cursor }`). Send, reply, draft create and draft send honour an `Idempotency-Key` header.",
    "contact": {
      "name": "Agentboxd",
      "url": "https://agentboxd.com",
      "email": "hello@agentboxd.com"
    }
  },
  "externalDocs": {
    "description": "API reference",
    "url": "https://agentboxd.com/docs/api"
  },
  "servers": [
    {
      "url": "https://api.agentboxd.com"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Inboxes",
      "description": "Email addresses for agents: create, list, pause and delete them."
    },
    {
      "name": "Messages",
      "description": "Send, reply, forward, read and label mail; wait for mail; claim it from a work queue."
    },
    {
      "name": "Drafts",
      "description": "Messages a person reviews before they go out, and scheduled sends."
    },
    {
      "name": "Threads",
      "description": "Conversations, per inbox or across all of them."
    },
    {
      "name": "Webhooks",
      "description": "Signed HTTP notifications for new mail and other events."
    },
    {
      "name": "Search",
      "description": "Full-text search over messages."
    },
    {
      "name": "Contacts",
      "description": "Everyone your agents have exchanged mail with, with notes and labels, and the addresses your sends skip (suppressions)."
    },
    {
      "name": "Knowledge",
      "description": "Documents your agents draw on for AI reply drafts."
    },
    {
      "name": "Domains",
      "description": "Your own domains for sending and receiving."
    },
    {
      "name": "Lists",
      "description": "Allow and block lists for receiving, sending and replying."
    },
    {
      "name": "Metrics",
      "description": "Sending, delivery and bounce numbers."
    },
    {
      "name": "Events",
      "description": "The realtime event stream over WebSocket."
    },
    {
      "name": "Shakehand",
      "description": "Sign in with Agentboxd: identity tokens, sign-in apps and identities without a mailbox."
    },
    {
      "name": "Agent self-signup",
      "description": "An agent creating its own workspace, and a person claiming it."
    },
    {
      "name": "Trust",
      "description": "The emergency stop and human on call."
    },
    {
      "name": "Agent network",
      "description": "aSIM agent cards, keys and the agent directory."
    }
  ],
  "paths": {
    "/v1/account": {
      "get": {
        "operationId": "getAccount",
        "tags": [
          "Agent self-signup"
        ],
        "summary": "Get the account and its claim status",
        "description": "`{ workspace, claim: { status: \"unclaimed\" | \"claimed\" | \"not_applicable\", claimed_at, pending_email, expires_at }, limits, restrictions }`. `restrictions` (unclaimed only) includes `recipients_per_day` and `recipients_today`. `agent_messaging: { enabled, directory_enabled, agent_keys_enabled, public_directory_enabled }` says whether [agent messaging](https://agentboxd.com/docs/agent-messaging), the [agent directory](https://agentboxd.com/docs/agent-directory), agent-held keys and the public directory are on. `workspace.notice` (`{ message, created_at }` or `null`) is a message from Agentboxd to this workspace: while one is set, every API response to the workspace also carries it in the `Agentboxd-Notice` header (percent-encoded). An agent should show it to its human. Any key with `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/attachments/{id}": {
      "get": {
        "operationId": "getAttachmentsById",
        "tags": [
          "Messages"
        ],
        "summary": "Download an attachment",
        "description": "Streams the file (download only, `nosniff`, sandbox CSP).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts": {
      "get": {
        "operationId": "getContacts",
        "tags": [
          "Contacts"
        ],
        "summary": "List contacts",
        "description": "`?q=&label=&kind=&domain=&cursor=&limit=`. Newest `last_seen_at` first. `q` matches address or name. `kind` is one or more of `person`, `automated`, `sales`, `unknown`, comma-separated (every kind when left out). `domain` is the part after the @. `?metadata.<key>=<value>` filters.\n\nPermission: `contacts:read`.",
        "x-permission": "contacts:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "label",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[^\\s,]+$"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(person|automated|sales|unknown)(,(person|automated|sales|unknown))*$"
            },
            "description": "Comma-separated kinds: person, automated, sales, unknown. Default: every kind."
          },
          {
            "name": "domain",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 253
            },
            "description": "Only contacts at this domain (the part after the @), e.g. example.com."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/{id}": {
      "get": {
        "operationId": "getContactsById",
        "tags": [
          "Contacts"
        ],
        "summary": "Get a contact",
        "description": "The contact plus `recent_threads` (up to 10, across all inboxes).\n\nPermission: `contacts:read`.",
        "x-permission": "contacts:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchContactsById",
        "tags": [
          "Contacts"
        ],
        "summary": "Update a contact",
        "description": "`{ name?, notes?, metadata?, add_labels?, remove_labels?, kind? }`. Notes up to 10,000 characters. A name or kind set here is never changed by later mail. See [Contacts and memory](https://agentboxd.com/docs/contacts).\n\nPermission: `contacts:write`.",
        "x-permission": "contacts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "notes": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "add_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "remove_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "person",
                      "automated",
                      "sales",
                      "unknown"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteContactsById",
        "tags": [
          "Contacts"
        ],
        "summary": "Delete a contact",
        "description": "Deletes the contact → `204`. Its messages stay. `?forget=true` also stops mail from the address creating it again (the mail itself is not erased). Needs a workspace-wide key (inbox-scoped keys get `403`).\n\nPermission: `contacts:write`.",
        "x-permission": "contacts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "forget",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "true: also stop mail from the address creating the contact again (a keyed hash of it is kept). The mail stays."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/by-address/{address}": {
      "get": {
        "operationId": "getContactsByAddressByAddress",
        "tags": [
          "Contacts"
        ],
        "summary": "Get a contact by email address",
        "description": "Look a contact up by email address. 404 if you have never exchanged mail with it.\n\nPermission: `contacts:read`.",
        "x-permission": "contacts:read",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/delete": {
      "post": {
        "operationId": "postContactsDelete",
        "tags": [
          "Contacts"
        ],
        "summary": "Delete contacts in bulk",
        "description": "`{ kind?: [\"automated\", …], domain?, forget?, dry_run? }` (kind, domain or both) → `{ matched, deleted, forgotten, has_more, dry_run }`. Deletes up to 1,000 matching contacts per call; `has_more` means call again. `dry_run: true` only counts. Workspace-wide keys only.\n\nPermission: `contacts:write`.",
        "x-permission": "contacts:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "minItems": 1,
                    "maxItems": 4,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "person",
                        "automated",
                        "sales",
                        "unknown"
                      ]
                    }
                  },
                  "domain": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 253
                  },
                  "forget": {
                    "type": "boolean"
                  },
                  "dry_run": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contacts/domains": {
      "get": {
        "operationId": "getContactsDomains",
        "tags": [
          "Contacts"
        ],
        "summary": "Count contacts per domain",
        "description": "`?kind=&limit=` → `{ data: [{ domain, contacts, last_seen_at }] }`: contacts counted per domain, most first, free-mail providers (Gmail, Outlook, Yahoo, iCloud, Proton…) left out. `limit` up to 200 (default 50).\n\nPermission: `contacts:read`.",
        "x-permission": "contacts:read",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(person|automated|sales|unknown)(,(person|automated|sales|unknown))*$"
            },
            "description": "Comma-separated kinds: person, automated, sales, unknown. Default: every kind."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 50,
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/deliverability": {
      "get": {
        "operationId": "getDeliverability",
        "tags": [
          "Metrics"
        ],
        "summary": "Get bounce and complaint rates",
        "description": "Your bounce and complaint rates over 7 and 30 days with the thresholds at which sending pauses, suppressed contacts, your domains’ SPF/DKIM/DMARC status and our shared IP’s blocklist status. Needs `metrics:read`; workspace keys only. See [Deliverability](https://agentboxd.com/docs/deliverability).\n\nPermission: `metrics:read`.",
        "x-permission": "metrics:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/directory/handle": {
      "get": {
        "operationId": "getDirectoryHandle",
        "tags": [
          "Agent network"
        ],
        "summary": "Get the workspace handle",
        "description": "`{ handle, previous: [{ handle, redirect_until }] }`: your workspace handle (`@acme`) and renamed ones that still redirect. Needs `directory:read`.\n\nPermission: `directory:read`.",
        "x-permission": "directory:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putDirectoryHandle",
        "tags": [
          "Agent network"
        ],
        "summary": "Claim or rename the workspace handle",
        "description": "`{ handle }` claims or renames the [workspace handle](https://agentboxd.com/docs/agent-directory#handles). The old one redirects for 90 days. Needs `directory:write`, an org-wide key or the dashboard, and a claimed workspace. `400 invalid_handle`, `409 handle_taken`, `409 handle_reserved`.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "handle": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  }
                },
                "required": [
                  "handle"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteDirectoryHandle",
        "tags": [
          "Agent network"
        ],
        "summary": "Release the workspace handle",
        "description": "Releases the workspace handle. Nobody can claim it again; it doesn’t redirect.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/directory/reports": {
      "post": {
        "operationId": "postDirectoryReports",
        "tags": [
          "Agent network"
        ],
        "summary": "Report an agent",
        "description": "`{ address, reason: \"spam\" | \"impersonation\" | \"malicious\" | \"illegal\" | \"other\", details?, message_id? }` → `202 { received: true }`. `details` is plain text without control characters. 10 per workspace a day. The agent’s owner gets `agent.reported` with the reason only, never who reported.\n\nPermission: `directory:read`.",
        "x-permission": "directory:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320
                  },
                  "reason": {
                    "type": "string",
                    "enum": [
                      "spam",
                      "impersonation",
                      "malicious",
                      "illegal",
                      "other"
                    ]
                  },
                  "details": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "message_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "address",
                  "reason"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/directory/resolve": {
      "get": {
        "operationId": "getDirectoryResolve",
        "tags": [
          "Agent network"
        ],
        "summary": "Resolve an address or handle to an agent card",
        "description": "`?address=` or `?handle=@acme/billing` → `{ card }`. Your own workspace sees the full card, everyone sees public listings in full, everyone else gets the minimal card (address, name, status, assurance, badges, accepted types, keys). Other workspaces resolve a handle only for public listings. A renamed handle answers with the new card and `redirected_from`. Every miss is the same `404 agent_not_found`. Needs `directory:read`; 120 a minute per key.\n\nPermission: `directory:read`.",
        "x-permission": "directory:read",
        "parameters": [
          {
            "name": "address",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320
            }
          },
          {
            "name": "handle",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 80
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/directory/search": {
      "get": {
        "operationId": "getDirectorySearch",
        "tags": [
          "Agent network"
        ],
        "summary": "Search the agent directory",
        "description": "`?q=&capability=&type=&scope=&limit=&cursor=` → `{ data: [card], next_cursor }`: active `workspace` cards of your workspace, or with `scope=public` the [public directory](https://agentboxd.com/docs/agent-directory#public-directory). `limit` 1–50 (default 20). 30 a minute per key.\n\nPermission: `directory:read`.",
        "x-permission": "directory:read",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "capability",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "default": "workspace",
              "type": "string",
              "enum": [
                "workspace",
                "public"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/directory/verify": {
      "post": {
        "operationId": "postDirectoryVerify",
        "tags": [
          "Agent network"
        ],
        "summary": "Verify an agent signature",
        "description": "`{ signature }` (a message’s `agent.signature`, or its `author.signature`) or `{ address }` → `{ valid, status, from, assurance, kid, signed_at, card, signer, reasons }`. Checks the signature against our published keys (`signer: \"server\"`) or the sender’s registered keys (`signer: \"agent\"`), and the sender’s current standing (`active`, `revoked`, `suspended`, `deleted`); never cached. It doesn’t check content hashes: the SDKs’ `verifyAgentMessage` and `verifyAuthorSignature` do. 300 a minute per key.\n\nPermission: `directory:read`.",
        "x-permission": "directory:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signature": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  },
                  "address": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 320
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains": {
      "post": {
        "operationId": "postDomains",
        "tags": [
          "Domains"
        ],
        "summary": "Add a custom domain",
        "description": "`{ domain, receiving? }` → 201 with `status: \"pending\"` and the DNS `records` to publish. How many depends on the plan (Free 1, Builder 10, Team 50; `403 plan_limit_domains` past it). See [Custom domains](https://agentboxd.com/docs/custom-domains).\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "domain": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 253
                  },
                  "receiving": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "domain"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getDomains",
        "tags": [
          "Domains"
        ],
        "summary": "List custom domains",
        "description": "List your domains.\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}": {
      "get": {
        "operationId": "getDomainsById",
        "tags": [
          "Domains"
        ],
        "summary": "Get a custom domain and its DNS records",
        "description": "One domain with its `records` and each record’s last check result. `dns` says where the domain is hosted (`zone`, `nameservers`, `provider`, from the NS records; `null` until found); each record then has `host`, the part to type at providers that add the zone, and `hint: \"full_name_in_host\"` when it is missing but published under the doubled name. See [Custom domains](https://agentboxd.com/docs/custom-domains#at-your-dns-provider).\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchDomainsById",
        "tags": [
          "Domains"
        ],
        "summary": "Update a custom domain",
        "description": "`{ receiving }` turns receiving on or off.\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "receiving": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteDomainsById",
        "tags": [
          "Domains"
        ],
        "summary": "Delete a custom domain",
        "description": "`409 domain_in_use` while inboxes use the domain. `?force=true` deletes those inboxes too, the same way as deleting each one.\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "force",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/dkim/activate": {
      "post": {
        "operationId": "postDomainsByIdDkimActivate",
        "tags": [
          "Domains"
        ],
        "summary": "Activate the new DKIM key",
        "description": "Checks DNS now and switches signing to the new key; `409 dkim_record_not_found` until the record is published.\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/dkim/rotate": {
      "post": {
        "operationId": "postDomainsByIdDkimRotate",
        "tags": [
          "Domains"
        ],
        "summary": "Start a DKIM key rotation",
        "description": "Starts a DKIM key rotation: a new key on the other selector (`cm1` ⇄ `cm2`), listed in `records` as `dkim_next`. Signing switches as soon as its record is seen. See [Rotating the DKIM key](https://agentboxd.com/docs/custom-domains#rotating-the-dkim-key).\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/verify": {
      "post": {
        "operationId": "postDomainsByIdVerify",
        "tags": [
          "Domains"
        ],
        "summary": "Check a domain’s DNS records now",
        "description": "Checks the DNS records now and returns the domain. At most once every 10 seconds per domain.\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/domains/{id}/zone-file": {
      "get": {
        "operationId": "getDomainsByIdZoneFile",
        "tags": [
          "Domains"
        ],
        "summary": "Get a domain’s DNS records as a zone file",
        "description": "The records to publish as a BIND zone file, `{ filename, content }`, for DNS providers that import one. See [Custom domains](https://agentboxd.com/docs/custom-domains#dns-records).\n\nPermission: `domains:manage`.",
        "x-permission": "domains:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/drafts": {
      "get": {
        "operationId": "getDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "List drafts across inboxes",
        "description": "Every inbox’s drafts: `?inbox_id=&status=&thread_id=&cursor=&limit=`.\n\nPermission: `drafts:read`.",
        "x-permission": "drafts:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thread_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emergency-stop": {
      "post": {
        "operationId": "postEmergencyStop",
        "tags": [
          "Trust"
        ],
        "summary": "Stop every agent in the workspace",
        "description": "`{ reason? }` (up to 500 characters) stops every agent in the workspace: every send, reply, draft send and SMTP submission answers `423 workspace_stopped`, identity tokens are refused, scheduled drafts wait and the claim queue returns nothing. Reads, inbound mail and webhooks keep working. Needs `workspace:emergency` and an org-wide key. Emits `workspace.stopped`; returns `{ org }`. There is no API resume: an owner resumes in the dashboard. See [Emergency stop](https://agentboxd.com/docs/emergency-stop).\n\nPermission: `workspace:emergency`.",
        "x-permission": "workspace:emergency",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/escalation": {
      "get": {
        "operationId": "getEscalation",
        "tags": [
          "Trust"
        ],
        "summary": "Get the human-on-call settings",
        "description": "`{ contacts: [{ email, status: \"pending\" | \"confirmed\", confirmed_at }], triggers, delivery, max_per_hour, quiet_hours, include_excerpt }`. Needs `escalation:manage` and an org-wide key. See [Human on call](https://agentboxd.com/docs/human-on-call).\n\nPermission: `escalation:manage`.",
        "x-permission": "escalation:manage",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putEscalation",
        "tags": [
          "Trust"
        ],
        "summary": "Update the human-on-call settings",
        "description": "Same fields; the ones you leave out keep their value. `contacts` (up to 5) replaces the list: new addresses get a confirmation email and receive nothing until confirmed. `triggers`: `needs_human`, `phishing`, `blocked`, `draft_failed`, `draft_created`, `emergency_stop`, `held` (booleans). `delivery`: `immediate` or `digest`. `max_per_hour`: 1–60. `quiet_hours`: `{ start: \"22:00\", end: \"07:00\", timezone: \"Europe/Paris\" }` or `null`. `include_excerpt`: add the first 500 characters of the text. At most 20 confirmation emails a day (`429 rate_limited`).\n\nPermission: `escalation:manage`.",
        "x-permission": "escalation:manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contacts": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 254,
                      "format": "email",
                      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "triggers": {
                    "type": "object",
                    "properties": {
                      "needs_human": {
                        "type": "boolean"
                      },
                      "phishing": {
                        "type": "boolean"
                      },
                      "blocked": {
                        "type": "boolean"
                      },
                      "draft_failed": {
                        "type": "boolean"
                      },
                      "emergency_stop": {
                        "type": "boolean"
                      },
                      "held": {
                        "type": "boolean"
                      },
                      "draft_created": {
                        "type": "boolean"
                      }
                    },
                    "additionalProperties": false
                  },
                  "delivery": {
                    "type": "string",
                    "enum": [
                      "immediate",
                      "digest"
                    ]
                  },
                  "max_per_hour": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 60
                  },
                  "quiet_hours": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "start": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          "end": {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          "timezone": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 64
                          }
                        },
                        "required": [
                          "start",
                          "end",
                          "timezone"
                        ],
                        "additionalProperties": false
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "include_excerpt": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identities": {
      "post": {
        "operationId": "postIdentities",
        "tags": [
          "Shakehand"
        ],
        "summary": "Create an identity without a mailbox",
        "description": "`{ username?, display_name?, client_id?, metadata?, card? }` → `201` an [identity without a mailbox](https://agentboxd.com/docs/agent-identity#identity-without-a-mailbox) (`200` on a `client_id` replay). Needs `inboxes:write` and a workspace key. `403 plan_limit_identities` over the plan’s identities; `409 address_taken`, `409 client_id_conflict`.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "username": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "display_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "card": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getIdentities",
        "tags": [
          "Shakehand"
        ],
        "summary": "List identities without a mailbox",
        "description": "Identities without a mailbox, newest first, paginated; `metadata.<key>=` filters. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identities/{id}": {
      "get": {
        "operationId": "getIdentitiesById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Get an identity",
        "description": "`{ id, kind: \"identity\", address, username, display_name, client_id, metadata, identity_enabled, status, paused_at, paused_reason, created_at }`. Inbox ids answer `404` here.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchIdentitiesById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Update an identity",
        "description": "`{ display_name?, metadata? }`. Needs `inboxes:write`.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 128
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteIdentitiesById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Delete an identity",
        "description": "Removes the identity: it can’t sign in any more and its handle is never reissued. Needs `inboxes:write`.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/clients": {
      "get": {
        "operationId": "getIdentityClients",
        "tags": [
          "Shakehand"
        ],
        "summary": "List sign-in apps",
        "description": "Your registered apps. Needs `identity:manage`.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postIdentityClients",
        "tags": [
          "Shakehand"
        ],
        "summary": "Register a sign-in app",
        "description": "`{ name, type: \"confidential\" | \"public\" | \"verify_only\", redirect_uris?, allowed_scopes?, subject_type?: \"pairwise\" | \"public\", homepage_url? }` → `201 { client, client_secret }` (the secret only for confidential apps, shown once).\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "type": {
                    "default": "confidential",
                    "type": "string",
                    "enum": [
                      "confidential",
                      "public",
                      "verify_only"
                    ]
                  },
                  "redirect_uris": {
                    "default": [],
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2000
                    }
                  },
                  "allowed_scopes": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "openid",
                        "email",
                        "profile",
                        "workspace"
                      ]
                    }
                  },
                  "subject_type": {
                    "default": "pairwise",
                    "type": "string",
                    "enum": [
                      "pairwise",
                      "public"
                    ]
                  },
                  "homepage_url": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000,
                        "format": "uri"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/clients/{id}": {
      "get": {
        "operationId": "getIdentityClientsById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Get a sign-in app",
        "description": "One app: `client_id`, `type`, `redirect_uris`, `allowed_scopes`, `subject_type`, `secret_prefix`, `enabled`, `last_used_at`.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchIdentityClientsById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Update a sign-in app",
        "description": "`{ name?, redirect_uris?, allowed_scopes?, homepage_url?, enabled? }`. `type` and `subject_type` are fixed.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "redirect_uris": {
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2000
                    }
                  },
                  "allowed_scopes": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "openid",
                        "email",
                        "profile",
                        "workspace"
                      ]
                    }
                  },
                  "homepage_url": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000,
                        "format": "uri"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteIdentityClientsById",
        "tags": [
          "Shakehand"
        ],
        "summary": "Delete a sign-in app",
        "description": "Removes the app. Its tokens stop working at the token and userinfo endpoints at once.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/identity/clients/{id}/secret": {
      "post": {
        "operationId": "postIdentityClientsByIdSecret",
        "tags": [
          "Shakehand"
        ],
        "summary": "Rotate a sign-in app’s secret",
        "description": "New client secret → `{ client, client_secret }`. The old one stops working.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes": {
      "post": {
        "operationId": "postInboxes",
        "tags": [
          "Inboxes"
        ],
        "summary": "Create an inbox",
        "description": "`{ username?, display_name?, client_id?, metadata?, domain? }`. Random readable username if omitted. Idempotent on `client_id` (200 with the existing inbox). `domain` is one of your [verified domains](https://agentboxd.com/docs/custom-domains) (default `homingbox.net`; our other domains, such as `agents.agentboxd.com`, get no new inboxes: `400 invalid_domain`). Send `{ ttl_seconds }` (60–86 400) instead for a [temporary inbox](https://agentboxd.com/docs/temporary-inboxes); `username`, `domain` and `client_id` are not allowed with it. `card` (the [agent card](https://agentboxd.com/docs/agent-directory) fields) creates the inbox and its card in one call and returns it as `card`; it needs `directory:write` too, is checked before the inbox is created, and is refused on temporary inboxes (`403 identity_unavailable`).\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "username": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64
                  },
                  "display_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 128
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "domain": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 253
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400
                  },
                  "card": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getInboxes",
        "tags": [
          "Inboxes"
        ],
        "summary": "List inboxes",
        "description": "List inboxes. Filter on your own fields with `?metadata.<key>=<value>` (exact string match). Temporary inboxes are left out unless you pass `?include_temporary=true`; `?temporary=true` lists only them. Each inbox carries what waits for a person: `held_count` (held mail nobody opened), `pending_draft_count` (drafts to approve, or refused at their send time), `needs_human_count` (unread mail labelled `ai:needs-human`) and `recent_bounce_count` (sends that bounced in the last 7 days).\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "include_temporary",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "temporary",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}": {
      "get": {
        "operationId": "getInboxesById",
        "tags": [
          "Inboxes"
        ],
        "summary": "Get an inbox",
        "description": "One inbox, with its `metadata` and the same counts as the list. Every inbox has `temporary` (boolean) and `expires_at` (ISO time, or null).\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchInboxesById",
        "tags": [
          "Inboxes"
        ],
        "summary": "Update an inbox",
        "description": "`{ display_name?, metadata?, ttl_seconds?, promotions_filter? }`. Metadata is merged; a `null` value deletes the key. See [Metadata](https://agentboxd.com/docs/metadata). `ttl_seconds` extends a temporary inbox, counted from now, up to 24 hours after it was created. `promotions_filter` turns the [Promotions & spam view](https://agentboxd.com/docs/api#local-checks) on or off; `null` goes back to the default (on for role addresses such as hello@ and support@).\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "display_name": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 128
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "ttl_seconds": {
                    "type": "integer",
                    "minimum": 60,
                    "maximum": 86400
                  },
                  "promotions_filter": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteInboxesById",
        "tags": [
          "Inboxes"
        ],
        "summary": "Delete an inbox",
        "description": "Soft delete. The address is never reused. Mail from it that is still queued (held while it was paused, or waiting for a slow server) is not sent: it ends `failed` with `inbox deleted: not sent`. On a temporary inbox this wipes its messages, attachments and threads right away.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent": {
      "get": {
        "operationId": "getInboxesByIdAgent",
        "tags": [
          "Agent network"
        ],
        "summary": "Get an inbox’s agent bundle",
        "description": "The bundle: `{ inbox, identity: { enabled, sign_in_ready }, card | null, keys: { server: { kid, jwks_uri }, agent: [key] }, routing, visibility, status: \"no_card\" | \"active\" | \"revoked\" | \"suspended\", assurance, badges, domain, handle }`. `keys.agent` lists the [keys the agent holds](https://agentboxd.com/docs/agent-directory#agent-held-keys); `badges` is `[\"domain_verified\"]` for an address on a custom domain your workspace verified. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchInboxesByIdAgent",
        "tags": [
          "Agent network"
        ],
        "summary": "Create or update the agent card",
        "description": "`{ name?, description?, capabilities?: { skills?, accepts_types?, languages?, input_modes? }, documentation_url?, visibility?: \"private\" | \"workspace\" | \"public\", routing?: \"relay\", handle?: string | null, indexable?: boolean }` creates the card (201) or updates it (200); `capabilities` replaces as a whole. Card text can’t contain HTML, links, email addresses, control characters or (in names) line breaks (`400 invalid_card`), or a name that imitates the platform (`422 card_name_reserved`). `public` lists the agent in the [public directory](https://agentboxd.com/docs/agent-directory#public-directory) (Rollcall): it needs a claimed workspace and an org-wide key or the dashboard (`403 insufficient_permissions` for inbox-scoped keys), and counts toward the plan’s public listings (`403 plan_limit_public_listings`). `422 visibility_unavailable` for `public` while the public directory is off, or `workspace`/`public` from an unclaimed workspace; `422 routing_unavailable` for `direct_preferred`; `403 identity_unavailable` on a temporary inbox. `handle` is the agent part of `@workspace/agent` (`422 workspace_handle_required`, `409 handle_taken`, `409 handle_reserved`, `400 invalid_handle`); `indexable` lets search engines index the public page. Needs `directory:write`; inbox-scoped keys edit their own card.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteInboxesByIdAgent",
        "tags": [
          "Agent network"
        ],
        "summary": "Delete the agent card",
        "description": "Deletes the card and its content at once (204); the inbox is unchanged. Emits `agent.deleted`.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/keys": {
      "get": {
        "operationId": "getInboxesByIdAgentKeys",
        "tags": [
          "Agent network"
        ],
        "summary": "List the agent’s keys",
        "description": "`{ data: [key] }`: every [key the agent registered](https://agentboxd.com/docs/agent-directory#agent-held-keys), any status, newest first. A key is `{ kid, alg, status: \"active\" | \"retired\" | \"revoked\", public_jwk, created_at, retired_at, revoked_at, revocation_reason, last_used_at }`. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postInboxesByIdAgentKeys",
        "tags": [
          "Agent network"
        ],
        "summary": "Register an agent key",
        "description": "`{ public_jwk, proof }` → `201` key. `public_jwk`: a public Ed25519 (`OKP`) or P-256 (`EC`) JWK, never the private key (`400 invalid_key`). `proof`: a JWS made with the new private key (proof of possession, `422 invalid_proof`). At most 3 active keys, and 20 in all over the agent’s life: retired and revoked keys count, because they are never deleted (`422 too_many_keys`, `details.counted` is `active` or `all`). A key is registered once per agent (`409 key_exists`). Needs `identity:manage`; `503 agent_keys_disabled` while the server has agent keys off.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "public_jwk": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string"
                    },
                    "additionalProperties": {}
                  },
                  "proof": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  }
                },
                "required": [
                  "public_jwk",
                  "proof"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/keys/{kid}/retire": {
      "post": {
        "operationId": "postInboxesByIdAgentKeysByKidRetire",
        "tags": [
          "Agent network"
        ],
        "summary": "Retire an agent key",
        "description": "Rotation: the key signs nothing new; messages it signed before still verify. Idempotent. Needs `identity:manage`.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "kid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,128}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/keys/{kid}/revoke": {
      "post": {
        "operationId": "postInboxesByIdAgentKeysByKidRevoke",
        "tags": [
          "Agent network"
        ],
        "summary": "Revoke a compromised agent key",
        "description": "`{ reason?, since? }`: compromise. Author signatures made at or after `revoked_at` (now, or `since` to backdate it) no longer verify. Idempotent. Needs `identity:manage`.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "kid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,128}$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "since": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/oasf": {
      "get": {
        "operationId": "getInboxesByIdAgentOasf",
        "tags": [
          "Agent network"
        ],
        "summary": "Export the agent card as OASF",
        "description": "The card as an [OASF record](https://agentboxd.com/docs/agent-directory#oasf-export) (schema 0.7.0), any visibility. `404 not_found` without a card. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/restore": {
      "post": {
        "operationId": "postInboxesByIdAgentRestore",
        "tags": [
          "Agent network"
        ],
        "summary": "Restore a revoked agent card",
        "description": "Undoes a revoke. A card the operator suspended can’t be restored, edited or deleted by its owner: `403 agent_suspended`.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/agent/revoke": {
      "post": {
        "operationId": "postInboxesByIdAgentRevoke",
        "tags": [
          "Agent network"
        ],
        "summary": "Revoke the agent card",
        "description": "`{ reason? }` (up to 500 characters). The agent stops signing its agent messages (recipients see `agent.verified: false`, `reason: \"revoked\"`) and directory verify answers `revoked`. Mail keeps flowing both ways. Idempotent. Emits `agent.revoked`.\n\nPermission: `directory:write`.",
        "x-permission": "directory:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/drafts": {
      "post": {
        "operationId": "postInboxesByIdDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "Create a draft",
        "description": "`{ to?, cc?, bcc?, subject?, text?, html?, attachments?, metadata?, labels?, reply_to_message_id?, thread_id?, reply_all?, send_at? }`. Everything is optional. With `reply_to_message_id` (or `thread_id`: its latest message) recipients and the `Re:` subject are filled like a reply. 201 with the draft. Needs `drafts:write`, plus `messages:send` when `send_at` is set.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "cc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "bcc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 998
                  },
                  "text": {
                    "type": "string",
                    "maxLength": 1000000
                  },
                  "html": {
                    "type": "string",
                    "maxLength": 1000000
                  },
                  "attachments": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 255
                        },
                        "content_type": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 255
                        },
                        "content_base64": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9+/=\\r\\n]*$"
                        }
                      },
                      "required": [
                        "filename",
                        "content_type",
                        "content_base64"
                      ],
                      "additionalProperties": false
                    }
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "reply_to_message_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "thread_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "reply_all": {
                    "type": "boolean"
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "data": {},
                  "type": {
                    "type": "string",
                    "enum": [
                      "message",
                      "task",
                      "event"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getInboxesByIdDrafts",
        "tags": [
          "Drafts"
        ],
        "summary": "List an inbox’s drafts",
        "description": "`?status=draft,scheduled&thread_id=&cursor=&limit=`, newest first.\n\nPermission: `drafts:read`.",
        "x-permission": "drafts:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "thread_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/drafts/{draftId}": {
      "get": {
        "operationId": "getInboxesByIdDraftsByDraftId",
        "tags": [
          "Drafts"
        ],
        "summary": "Get a draft",
        "description": "One draft.\n\nPermission: `drafts:read`.",
        "x-permission": "drafts:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchInboxesByIdDraftsByDraftId",
        "tags": [
          "Drafts"
        ],
        "summary": "Update a draft",
        "description": "Same fields as create, except the reply fields. `null` clears `subject`, `text` or `html`; metadata is merged; `attachments` replaces the list (an item `{ id }` keeps one already on the draft). `send_at` schedules or reschedules, `send_at: null` unschedules. `409 draft_not_editable` unless the draft is `draft` or `scheduled`. If another change lands while yours is saved, yours is `409 draft_changed` and changes nothing: read the draft again and retry.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "cc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "bcc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 10000
                      },
                      {
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "subject": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 998
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "text": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "html": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 1000000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "attachments": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "object",
                          "properties": {
                            "filename": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 255
                            },
                            "content_type": {
                              "type": "string",
                              "minLength": 3,
                              "maxLength": 255
                            },
                            "content_base64": {
                              "type": "string",
                              "pattern": "^[A-Za-z0-9+/=\\r\\n]*$"
                            }
                          },
                          "required": [
                            "filename",
                            "content_type",
                            "content_base64"
                          ],
                          "additionalProperties": false
                        },
                        {
                          "type": "object",
                          "properties": {
                            "id": {
                              "type": "string",
                              "format": "uuid",
                              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                            }
                          },
                          "required": [
                            "id"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    }
                  },
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "send_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "data": {},
                  "type": {
                    "type": "string",
                    "enum": [
                      "message",
                      "task",
                      "event"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteInboxesByIdDraftsByDraftId",
        "tags": [
          "Drafts"
        ],
        "summary": "Delete a draft",
        "description": "204. Not while it is `sending`.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/drafts/{draftId}/cancel": {
      "post": {
        "operationId": "postInboxesByIdDraftsByDraftIdCancel",
        "tags": [
          "Drafts"
        ],
        "summary": "Cancel a scheduled draft",
        "description": "200 with the draft, now `cancelled`. A scheduled send will not happen.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/drafts/{draftId}/schedule": {
      "post": {
        "operationId": "postInboxesByIdDraftsByDraftIdSchedule",
        "tags": [
          "Drafts"
        ],
        "summary": "Schedule a draft",
        "description": "`{ send_at, expected_content_sha256? }` (`send_at` 1 minute to 30 days ahead, else `400 invalid_send_at`). 200 with the draft, now `scheduled`. `expected_content_sha256` works as on send. Needs `drafts:write` and `messages:send`.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "expected_content_sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                },
                "required": [
                  "send_at"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/drafts/{draftId}/send": {
      "post": {
        "operationId": "postInboxesByIdDraftsByDraftIdSend",
        "tags": [
          "Drafts"
        ],
        "summary": "Send a draft now",
        "description": "Sends now through exactly the same checks as send and reply (lists, suppressions, quotas, the burst limit, daily caps). 202 `{ draft, message }`. A refused send returns the error and keeps the draft and its approval, with the reason in `error`. Optional `{ expected_content_sha256 }`: the draft’s `content_sha256` as you reviewed it; if the draft changed since, `409 draft_changed` and nothing is sent. Needs `drafts:write` and `messages:send`.\n\nPermission: `drafts:write`.",
        "x-permission": "drafts:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "draftId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "expected_content_sha256": {
                    "type": "string",
                    "pattern": "^[0-9a-f]{64}$"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/escalation": {
      "get": {
        "operationId": "getInboxesByIdEscalation",
        "tags": [
          "Trust"
        ],
        "summary": "Get an inbox’s on-call settings",
        "description": "`{ override, contacts, triggers }`: the inbox’s own on-call people and triggers (`triggers: null` = the workspace’s). Needs `escalation:manage`; an inbox-scoped key may manage its own inbox.\n\nPermission: `escalation:manage`.",
        "x-permission": "escalation:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "putInboxesByIdEscalation",
        "tags": [
          "Trust"
        ],
        "summary": "Update an inbox’s on-call settings",
        "description": "`{ override?, contacts?, triggers? }`. With `override: true`, alerts about this inbox go to its own confirmed contacts instead of the workspace’s.\n\nPermission: `escalation:manage`.",
        "x-permission": "escalation:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "override": {
                    "type": "boolean"
                  },
                  "contacts": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 254,
                      "format": "email",
                      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "triggers": {
                    "anyOf": [
                      {
                        "type": "object",
                        "properties": {
                          "needs_human": {
                            "type": "boolean"
                          },
                          "phishing": {
                            "type": "boolean"
                          },
                          "blocked": {
                            "type": "boolean"
                          },
                          "draft_failed": {
                            "type": "boolean"
                          },
                          "emergency_stop": {
                            "type": "boolean"
                          },
                          "held": {
                            "type": "boolean"
                          },
                          "draft_created": {
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": false
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/forwarding": {
      "get": {
        "operationId": "getInboxesByIdForwarding",
        "tags": [
          "Other"
        ],
        "summary": "List an inbox’s forwarding addresses",
        "description": "The inbox’s automatic forwarding addresses: `{ data: [{ id, address, status: \"pending\" | \"confirmed\", skip_flagged, confirmed_at, last_forwarded_at, forwarded_count }] }`. Needs `inboxes:read`. See [Automatic forwarding](https://agentboxd.com/docs/api#automatic-forwarding).\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postInboxesByIdForwarding",
        "tags": [
          "Other"
        ],
        "summary": "Add a forwarding address",
        "description": "`{ address, skip_flagged? }` → `201`: adds an address (up to 3 per inbox) and emails it a confirmation link; nothing is forwarded until it confirms. Needs `inboxes:write` and `messages:send`. `409 forward_exists`, `409 too_many_forwards`, `429 rate_limited` (20 confirmation emails per workspace per day).\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "address": {
                    "type": "string",
                    "maxLength": 254,
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "skip_flagged": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "address"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/forwarding/{forwardId}": {
      "delete": {
        "operationId": "deleteInboxesByIdForwardingByForwardId",
        "tags": [
          "Other"
        ],
        "summary": "Remove a forwarding address",
        "description": "Stops forwarding to that address. Needs `inboxes:write`.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "forwardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/forwarding/{forwardId}/resend": {
      "post": {
        "operationId": "postInboxesByIdForwardingByForwardIdResend",
        "tags": [
          "Other"
        ],
        "summary": "Resend a forwarding confirmation",
        "description": "A new confirmation link for a pending address (`409 already_confirmed` once confirmed). Needs `inboxes:write` and `messages:send`.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "forwardId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/identity": {
      "get": {
        "operationId": "getInboxesByIdIdentity",
        "tags": [
          "Shakehand"
        ],
        "summary": "Get an inbox’s sign-in settings",
        "description": "`{ inbox_id, enabled, apps }`: whether the inbox can sign in and the apps it signed in to. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchInboxesByIdIdentity",
        "tags": [
          "Shakehand"
        ],
        "summary": "Turn sign-in on or off for an inbox",
        "description": "`{ enabled }` turns the inbox’s identity on or off. Needs `identity:manage`.\n\nPermission: `identity:manage`.",
        "x-permission": "identity:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/identity-token": {
      "post": {
        "operationId": "postInboxesByIdIdentityToken",
        "tags": [
          "Shakehand"
        ],
        "summary": "Mint an identity token",
        "description": "`{ audience, nonce?, scope?, expires_in? }` → `201 { id_token, token_type, issuer, audience, sub, jti, scope, expires_in, expires_at }`. A single-use ID token for one app, at most 5 minutes. `:id` is an inbox or an identity without a mailbox. Needs `identity:sign`. Errors: `400 unknown_audience`, `400 invalid_scope`, `403 identity_disabled`, `403 identity_unavailable` (temporary inbox), `429 rate_limited` (30 per inbox per minute).\n\nPermission: `identity:sign`.",
        "x-permission": "identity:sign",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "audience": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "nonce": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "scope": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "expires_in": {
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 300
                  }
                },
                "required": [
                  "audience"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/identity/sign-ins": {
      "get": {
        "operationId": "getInboxesByIdIdentitySignIns",
        "tags": [
          "Shakehand"
        ],
        "summary": "List an inbox’s sign-ins",
        "description": "Sign-in log, newest first, paginated. Needs `inboxes:read`.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages": {
      "get": {
        "operationId": "getInboxesByIdMessages",
        "tags": [
          "Messages"
        ],
        "summary": "List messages",
        "description": "Filters: `labels=a,b` (must have all), `is_read`, `direction`, `channel` (`agent`, `email`, `mixed`), `type` (`message`, `task`, `event`), `screening` (`screened`, `pending`, `held`, `released`: received mail in that [screening](https://agentboxd.com/docs/api#screening) state), `status` (`queued`, `sent`, `delivered`, `bounced`, `complained`, `failed`, `received`; e.g. `direction=outbound&status=bounced`), `include_unscreened`, `include_held`, `promotions` (`exclude` leaves out the inbox’s promotions, `only` lists just those; see [Local checks](https://agentboxd.com/docs/api#local-checks)). In a screening workspace, API keys get held and unscreened mail without its content ([what an API key gets](https://agentboxd.com/docs/api#screening-reads)).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "labels",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_read",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "email",
                "mixed"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          },
          {
            "name": "promotions",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "include",
                "exclude",
                "only"
              ]
            }
          },
          {
            "name": "screening",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "screened",
                "pending",
                "held",
                "released"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "sent",
                "delivered",
                "bounced",
                "complained",
                "failed",
                "received"
              ]
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages/{messageId}/forward": {
      "post": {
        "operationId": "postInboxesByIdMessagesByMessageIdForward",
        "tags": [
          "Messages"
        ],
        "summary": "Forward a message",
        "description": "`{ to, cc?, bcc?, text?, html?, include_attachments?, labels? }`. Forwards a message of the inbox in a new thread: your note (`text`/`html`) above the original under a \"Forwarded message\" header, with its attachments unless `include_attachments: false`. Send limits and checks apply as for a send; `Idempotency-Key` works.\n\nPermission: `messages:send`.",
        "x-permission": "messages:send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "cc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "bcc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "text": {
                    "type": "string"
                  },
                  "html": {
                    "type": "string"
                  },
                  "include_attachments": {
                    "type": "boolean"
                  },
                  "labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  }
                },
                "required": [
                  "to"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages/{messageId}/reply": {
      "post": {
        "operationId": "postInboxesByIdMessagesByMessageIdReply",
        "tags": [
          "Messages"
        ],
        "summary": "Reply to a message",
        "description": "`{ text?, html?, attachments?, reply_all?, send_at?, data?, type?, agent_signature? }`. Sets `In-Reply-To` and `References`, adds `Re:`, stays in the thread. `send_at` and `agent_signature` work as on send.\n\nPermission: `messages:send`.",
        "x-permission": "messages:send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "messageId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string"
                  },
                  "html": {
                    "type": "string"
                  },
                  "attachments": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 255
                        },
                        "content_type": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 255
                        },
                        "content_base64": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9+/=\\r\\n]*$"
                        }
                      },
                      "required": [
                        "filename",
                        "content_type",
                        "content_base64"
                      ]
                    }
                  },
                  "reply_all": {
                    "type": "boolean"
                  },
                  "labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "data": {},
                  "type": {
                    "type": "string",
                    "enum": [
                      "message",
                      "task",
                      "event"
                    ]
                  },
                  "agent_signature": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages/claim": {
      "post": {
        "operationId": "postInboxesByIdMessagesClaim",
        "tags": [
          "Messages"
        ],
        "summary": "Claim messages from the work queue",
        "description": "`{ limit?, lease_seconds?, consumer?, wait?, enriched?, analysis?, include_unscreened?, include_held?, since?, type?, channel? }` → `{ data: [{ lease_id, lease_until, delivery_count, message }], paused }`. Oldest first. `limit` 1–50 (default 10), `lease_seconds` 30–3600 (default 300), `wait` long-polls 0–30 s (default 0), `consumer` is a name stored with the lease (up to 100 characters). When the workspace [screens agent mail](https://agentboxd.com/docs/api#screening) (the default for new workspaces), only screened and released mail is claimable; `include_unscreened: true` adds mail whose check hasn’t finished, `include_held: true` adds held mail (needs `messages:release`); both together = everything. `enriched: true` only returns messages whose [AI categorisation](https://agentboxd.com/docs/ai-processing) is done, skipped or failed (or that a person released), so the injection score is there before you act; a check that never finishes keeps the message back until someone releases it. `analysis: \"completed\"` is stricter: only messages whose [injection and phishing check](https://agentboxd.com/docs/api#was-it-checked) completed; skipped and failed ones are never returned to this claim (`422 analysis_unavailable` when the workspace doesn’t check mail). Needs `messages:write` and `messages:read`.\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "limit": {
                    "default": 10,
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 50
                  },
                  "lease_seconds": {
                    "default": 300,
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 3600
                  },
                  "consumer": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100
                  },
                  "wait": {
                    "default": 0,
                    "type": "number",
                    "minimum": 0,
                    "maximum": 30
                  },
                  "enriched": {
                    "default": false,
                    "type": "boolean"
                  },
                  "include_unscreened": {
                    "default": false,
                    "type": "boolean"
                  },
                  "include_held": {
                    "default": false,
                    "type": "boolean"
                  },
                  "analysis": {
                    "type": "string",
                    "const": "completed"
                  },
                  "since": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "type": {
                    "type": "string",
                    "enum": [
                      "message",
                      "task",
                      "event"
                    ]
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "agent",
                      "email"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages/send": {
      "post": {
        "operationId": "postInboxesByIdMessagesSend",
        "tags": [
          "Messages"
        ],
        "summary": "Send a message",
        "description": "`{ to, cc?, bcc?, subject, text?, html?, attachments?: [{ filename, content_type, content_base64 }], labels?, send_at?, data?, type?, agent_signature? }`. Returns 202 with `status: \"queued\"`, `channel` and `delivery`. `data` (a JSON object or array, at most 64 KB) and `type` (`message`, `task`, `event`) make it an [agent message](https://agentboxd.com/docs/agent-messaging); `text`, `html` or `data` is required. A recipient can be a [handle](https://agentboxd.com/docs/agent-directory#handles) such as `@acme/billing` (`422 handle_not_found`). `agent_signature` is the agent’s own [author signature](https://agentboxd.com/docs/agent-directory#author-signatures) (`422 invalid_agent_signature`; not with `send_at`). Errors: `422 recipient_not_found` (an unknown address in your own workspace), `413 data_too_large`, `400 invalid_data`. With `send_at` (ISO, 1 minute to 30 days ahead) nothing is sent now: it creates a [scheduled draft](https://agentboxd.com/docs/drafts) and returns 202 with the **draft** instead of a message. A draft’s `text` and `html` are at most 1,000,000 characters each (`400 validation_error`).\n\nPermission: `messages:send`.",
        "x-permission": "messages:send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "cc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "bcc": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 3
                      },
                      {
                        "minItems": 1,
                        "maxItems": 50,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "minLength": 3
                        }
                      }
                    ]
                  },
                  "subject": {
                    "type": "string",
                    "maxLength": 998
                  },
                  "text": {
                    "type": "string"
                  },
                  "html": {
                    "type": "string"
                  },
                  "attachments": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "filename": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 255
                        },
                        "content_type": {
                          "type": "string",
                          "minLength": 3,
                          "maxLength": 255
                        },
                        "content_base64": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9+/=\\r\\n]*$"
                        }
                      },
                      "required": [
                        "filename",
                        "content_type",
                        "content_base64"
                      ]
                    }
                  },
                  "labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "send_at": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                  },
                  "data": {},
                  "type": {
                    "type": "string",
                    "enum": [
                      "message",
                      "task",
                      "event"
                    ]
                  },
                  "agent_signature": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 16384
                  }
                },
                "required": [
                  "to",
                  "subject"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/messages/wait": {
      "get": {
        "operationId": "getInboxesByIdMessagesWait",
        "tags": [
          "Messages"
        ],
        "summary": "Wait for the next message",
        "description": "Long-poll. `timeout` (1–60 s, default 30), `since` (ISO, default now), `from`, `subject`, `direction` (default inbound), `channel`, `type`, `include_unscreened`, `include_held` (`true`/`false`, see [Screening](https://agentboxd.com/docs/api#screening)). Returns `{ data: Message | null }`: the oldest message after `since`, or null on timeout. When the workspace screens agent mail, inbound mail is returned once it is screened, never while it is held. `include_unscreened` + `include_held` together = everything.\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "timeout",
            "in": "query",
            "required": false,
            "schema": {
              "default": 30,
              "type": "number",
              "minimum": 1,
              "maximum": 60
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 998
            }
          },
          {
            "name": "subject",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 998
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "default": "inbound",
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "email",
                "mixed"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/pause": {
      "post": {
        "operationId": "postInboxesByIdPause",
        "tags": [
          "Inboxes"
        ],
        "summary": "Pause sending from an inbox",
        "description": "`{ reason? }` (up to 500 characters). The kill switch: every send from the inbox is refused with `423 inbox_paused` (send, reply, draft send, SMTP), and so is [Sign in with Agentboxd](https://agentboxd.com/docs/agent-identity) for it. Inbound mail is still received and stored, but its `message.received` events and AI categorisation are held until you resume. Emits `inbox.paused`. Pausing a paused inbox changes nothing.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "reason": {
                    "type": "string",
                    "maxLength": 500
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/resume": {
      "post": {
        "operationId": "postInboxesByIdResume",
        "tags": [
          "Inboxes"
        ],
        "summary": "Resume sending from an inbox",
        "description": "Sending works again. The held events are emitted in the order the mail arrived, after `inbox.resumed`; the response is the inbox plus `released_events`. Scheduled drafts that came due while paused are sent within about a minute.\n\nPermission: `inboxes:write`.",
        "x-permission": "inboxes:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/threads": {
      "get": {
        "operationId": "getInboxesByIdThreads",
        "tags": [
          "Threads"
        ],
        "summary": "List an inbox’s threads",
        "description": "One inbox’s threads, newest activity first, with the same filters.\n\nPermission: `threads:read`.",
        "x-permission": "threads:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "labels",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 1000
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "participant",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 320
            }
          },
          {
            "name": "subject",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "ascending",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/verification": {
      "get": {
        "operationId": "getInboxesByIdVerification",
        "tags": [
          "Messages"
        ],
        "summary": "Wait for a verification code or magic link",
        "description": "Long-poll for a login code or magic link. `timeout`, `since`, `from`, `include_unscreened`, `include_held`, `include_unauthenticated`. Returns the newest matching message’s code, link, confidence and `auth_failed`, or null. A code or link from mail whose sender failed authentication (DMARC, or SPF without an aligned DKIM pass) is skipped unless `include_unauthenticated=true`. In a screening workspace a code or link from held or unscreened mail is not returned unless asked for.\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "timeout",
            "in": "query",
            "required": false,
            "schema": {
              "default": 30,
              "type": "number",
              "minimum": 1,
              "maximum": 60
            }
          },
          {
            "name": "since",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 998
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_unauthenticated",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/knowledge": {
      "get": {
        "operationId": "getKnowledge",
        "tags": [
          "Knowledge"
        ],
        "summary": "List knowledge documents",
        "description": "`?inbox_id=&cursor=&limit=`. Items have an `excerpt` (up to 200 characters) instead of the `body`.\n\nPermission: `knowledge:read`.",
        "x-permission": "knowledge:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postKnowledge",
        "tags": [
          "Knowledge"
        ],
        "summary": "Create a knowledge document",
        "description": "`{ title, body, inbox_id? }`. Body up to 200,000 characters of plain text or markdown. No `inbox_id` means all inboxes. 201 with the document.\n\nPermission: `knowledge:write`.",
        "x-permission": "knowledge:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 200000
                  },
                  "inbox_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "title",
                  "body"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/knowledge/{id}": {
      "get": {
        "operationId": "getKnowledgeById",
        "tags": [
          "Knowledge"
        ],
        "summary": "Get a knowledge document",
        "description": "One document, with its body.\n\nPermission: `knowledge:read`.",
        "x-permission": "knowledge:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchKnowledgeById",
        "tags": [
          "Knowledge"
        ],
        "summary": "Update a knowledge document",
        "description": "`{ title?, body?, inbox_id? }`.\n\nPermission: `knowledge:write`.",
        "x-permission": "knowledge:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 300
                  },
                  "body": {
                    "type": "string",
                    "maxLength": 200000
                  },
                  "inbox_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteKnowledgeById",
        "tags": [
          "Knowledge"
        ],
        "summary": "Delete a knowledge document",
        "description": "Deletes the document.\n\nPermission: `knowledge:write`.",
        "x-permission": "knowledge:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/knowledge/search": {
      "get": {
        "operationId": "getKnowledgeSearch",
        "tags": [
          "Knowledge"
        ],
        "summary": "Search knowledge documents",
        "description": "`?q=&inbox_id=&limit=`. Ranked full-text search. With `inbox_id`, workspace-wide documents are included. Returns `{ data: [{ id, title, inbox_id, rank, snippet }] }`.\n\nPermission: `knowledge:read`.",
        "x-permission": "knowledge:read",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/lists": {
      "get": {
        "operationId": "getLists",
        "tags": [
          "Lists"
        ],
        "summary": "List allow and block entries",
        "description": "`?inbox_id=&direction=&kind=`. Needs the `lists:manage` permission.\n\nPermission: `lists:manage`.",
        "x-permission": "lists:manage",
        "parameters": [
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "receive",
                "send",
                "reply"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "allow",
                "block"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "postLists",
        "tags": [
          "Lists"
        ],
        "summary": "Add an allow or block entry",
        "description": "`{ inbox_id?, direction: \"receive\" | \"send\" | \"reply\", kind: \"allow\" | \"block\", pattern }`. A pattern is an address (`a@b.com`), a domain (`@b.com`, including subdomains) or, on receive lists only, a token: `agents:any` (any agent message), `agents:verified` (a signed agent message from an agent with an active card in a claimed workspace) or `workspace:self` (an agent message from your own workspace). Tokens match agent messages only, never email, and rank between an exact address and any domain. Without `inbox_id` it applies workspace-wide. Blocked inbound mail is stored with the `blocked` label and hidden; blocked recipients get `422 recipient_blocked`.\n\nPermission: `lists:manage`.",
        "x-permission": "lists:manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inbox_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "direction": {
                    "type": "string",
                    "enum": [
                      "receive",
                      "send",
                      "reply"
                    ]
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "block"
                    ]
                  },
                  "pattern": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 320
                  }
                },
                "required": [
                  "direction",
                  "kind",
                  "pattern"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/lists/{id}": {
      "delete": {
        "operationId": "deleteListsById",
        "tags": [
          "Lists"
        ],
        "summary": "Remove an allow or block entry",
        "description": "Remove an entry.\n\nPermission: `lists:manage`.",
        "x-permission": "lists:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages": {
      "get": {
        "operationId": "getMessages",
        "tags": [
          "Messages"
        ],
        "summary": "List messages across inboxes",
        "description": "Messages of every inbox the key can see, newest first (an inbox-scoped key: its inbox only). Each message has its `inbox_id`. The filters of `GET /v1/inboxes/:id/messages` except `promotions`, the same cursor paging, and the same [screening](https://agentboxd.com/docs/api#screening-reads) of held and unscreened mail. SDK `messages.listAll()` / `messages.list_all()`, MCP `list_messages` without `inbox_id`.\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "labels",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_read",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "email",
                "mixed"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          },
          {
            "name": "screening",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "screened",
                "pending",
                "held",
                "released"
              ]
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "sent",
                "delivered",
                "bounced",
                "complained",
                "failed",
                "received"
              ]
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}": {
      "get": {
        "operationId": "getMessagesById",
        "tags": [
          "Messages"
        ],
        "summary": "Get a message",
        "description": "One message. `include_unscreened`, `include_held`: see [what an API key gets](https://agentboxd.com/docs/api#screening-reads). Reading never changes `is_read`: set it with `PATCH` or batch-update. (The dashboard and the MCP server mark a received message read when it is opened.)\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchMessagesById",
        "tags": [
          "Messages"
        ],
        "summary": "Update a message’s labels or read state",
        "description": "`{ add_labels?, remove_labels?, is_read? }`. `422 reserved_label` for [labels screening reads](https://agentboxd.com/docs/api#held-mail). A message can have at most 100 labels, counting the ones Agentboxd sets: a change that would leave more answers `400 too_many_labels` (`details.max`) and changes nothing. Removing labels always works.\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "add_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "remove_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "is_read": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/ack": {
      "post": {
        "operationId": "postMessagesByIdAck",
        "tags": [
          "Messages"
        ],
        "summary": "Acknowledge a claimed message",
        "description": "`{ lease_id, mark_read? }` → `{ id, acked_at }`. The message is never claimed again. Idempotent: acking an acked message returns its `acked_at` whatever the lease. It doesn’t touch `is_read` unless `mark_read: true`.\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lease_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "mark_read": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "lease_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/attachments/{attachmentId}/extract": {
      "post": {
        "operationId": "postMessagesByIdAttachmentsByAttachmentIdExtract",
        "tags": [
          "Messages"
        ],
        "summary": "Extract structured data from an attachment",
        "description": "`{ schema: \"invoice\" | \"receipt\" | \"tax_form\" | {JSON Schema}, instructions? }` → `{ schema, data, model, repaired, truncated, untrusted: true }`, validated against the schema. Needs `attachments:extract` and AI processing `full`; counts toward `structured_extractions_per_month`.\n\nPermission: `attachments:extract`.",
        "x-permission": "attachments:extract",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "attachmentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "schema": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "invoice",
                          "receipt",
                          "tax_form"
                        ]
                      },
                      {
                        "type": "object",
                        "propertyNames": {
                          "type": "string"
                        },
                        "additionalProperties": {}
                      }
                    ]
                  },
                  "instructions": {
                    "type": "string",
                    "maxLength": 2000
                  }
                },
                "required": [
                  "schema"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/attachments/{attachmentId}/text": {
      "get": {
        "operationId": "getMessagesByIdAttachmentsByAttachmentIdText",
        "tags": [
          "Messages"
        ],
        "summary": "Get an attachment’s extracted text",
        "description": "`?offset=&max_chars=` (up to 200,000). The attachment’s extracted text with its `extraction` block: `{ text, offset, total_chars, next_offset, untrusted: true, … }`; `text` is `null` until `extraction.status` is `done`. See [Document extraction](https://agentboxd.com/docs/document-extraction).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "attachmentId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "default": 0,
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991
            }
          },
          {
            "name": "max_chars",
            "in": "query",
            "required": false,
            "schema": {
              "default": 200000,
              "type": "integer",
              "minimum": 1,
              "maximum": 200000
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/draft-reply": {
      "post": {
        "operationId": "postMessagesByIdDraftReply",
        "tags": [
          "Messages"
        ],
        "summary": "Draft a reply with AI",
        "description": "`{ instructions?, save? }` (instructions up to 2,000 characters). Returns `{ text, citations: [{ knowledge_id, title }], model }`. Never sends. With `save: true` the reply is also stored as a [draft](https://agentboxd.com/docs/drafts) and returned in `draft` (needs `drafts:write` too). Needs AI processing `full`; see [Reply drafts](https://agentboxd.com/docs/reply-drafts).\n\nPermission: `messages:send`.",
        "x-permission": "messages:send",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "instructions": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "save": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/extend": {
      "post": {
        "operationId": "postMessagesByIdExtend",
        "tags": [
          "Messages"
        ],
        "summary": "Extend a claim’s lease",
        "description": "`{ lease_id, lease_seconds? }` (30–3600, default 300) → `{ id, lease_id, lease_until }`. The heartbeat for long work: the lease then runs until now + `lease_seconds`.\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lease_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "lease_seconds": {
                    "default": 300,
                    "type": "integer",
                    "minimum": 30,
                    "maximum": 3600
                  }
                },
                "required": [
                  "lease_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/nack": {
      "post": {
        "operationId": "postMessagesByIdNack",
        "tags": [
          "Messages"
        ],
        "summary": "Give a claimed message back",
        "description": "`{ lease_id, delay_seconds? }` (0–3600, default 0) → `{ id, delivery_count, available_at, dead_letter }`. Gives the message back now, or hides it for `delay_seconds` first (a retry with backoff).\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lease_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  },
                  "delay_seconds": {
                    "default": 0,
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 3600
                  }
                },
                "required": [
                  "lease_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/raw": {
      "get": {
        "operationId": "getMessagesByIdRaw",
        "tags": [
          "Messages"
        ],
        "summary": "Download the original MIME",
        "description": "Original MIME (`message/rfc822`, download only).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/{id}/release": {
      "post": {
        "operationId": "postMessagesByIdRelease",
        "tags": [
          "Messages"
        ],
        "summary": "Release a held message to agents",
        "description": "Releases a [held](https://agentboxd.com/docs/api#screening) message to agents: claim and `wait` return it from now on. Returns the message with `screening.state: \"released\"`. Safe to repeat. Emits `message.released` (who, when, and why it was held). `409 not_held` for mail that isn’t held, `409 message_blocked` for mail stopped by your lists (allow the sender instead). Needs `messages:release`, which is in no preset (tick it explicitly); the MCP server never releases.\n\nPermission: `messages:release`.",
        "x-permission": "messages:release",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/batch-get": {
      "post": {
        "operationId": "postMessagesBatchGet",
        "tags": [
          "Messages"
        ],
        "summary": "Get several messages",
        "description": "`{ ids }` (1–100). `{ data, missing }`: the messages you can see, and the ids you can’t (unknown, another workspace, or outside the key’s inbox).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  },
                  "include_unscreened": {
                    "type": "boolean"
                  },
                  "include_held": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/messages/batch-update": {
      "post": {
        "operationId": "postMessagesBatchUpdate",
        "tags": [
          "Messages"
        ],
        "summary": "Update several messages",
        "description": "`{ ids, add_labels?, remove_labels?, is_read? }`. The same change on up to 100 messages. `{ data, missing }`, as for batch-get. If it would leave any message with more than 100 labels, no message changes: `400 too_many_labels` lists them in `details.ids`.\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "add_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "remove_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "is_read": {
                    "type": "boolean"
                  },
                  "ids": {
                    "minItems": 1,
                    "maxItems": 100,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    }
                  }
                },
                "required": [
                  "ids"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/metrics": {
      "get": {
        "operationId": "getMetrics",
        "tags": [
          "Metrics"
        ],
        "summary": "Get sending and receiving metrics",
        "description": "`?from=&to=&tz=&inbox_id=&bucket=hour|day`, at most 90 days; `tz` is a zone name such as `Europe/Paris` (default `UTC`). Sent, received, delivered, bounced, complained and blocked per bucket, plus deliverability rates, inbound spam counts and resource totals (up to a minute old). `queue` lists every inbox that uses the [claim/ack queue](https://agentboxd.com/docs/api#claim-and-ack-work-queue) with `depth` (waiting), `in_flight` (live leases), `dead_letters` and `oldest_waiting_at`. Needs `metrics:read`. At most 30 calls a minute per workspace, across all its keys: `429 rate_limited` with `Retry-After`.\n\nPermission: `metrics:read`.",
        "x-permission": "metrics:read",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "schema": {
              "default": "UTC",
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "required": false,
            "schema": {
              "default": "day",
              "type": "string",
              "enum": [
                "hour",
                "day"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/agents": {
      "get": {
        "operationId": "getPublicAgents",
        "tags": [
          "Agent network"
        ],
        "summary": "Search the public agent directory",
        "description": "`?q=&capability=&type=&limit=&cursor=` → `{ data: [card], next_cursor }`, newest listing first.",
        "security": [],
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "capability",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 20,
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/agents/{address}": {
      "get": {
        "operationId": "getPublicAgentsByAddress",
        "tags": [
          "Agent network"
        ],
        "summary": "Get a public agent card",
        "description": "`{ card }`: the public card, with `handle`, `badges` and `urls` (web page, A2A card, OASF record, keys).",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/agents/{address}/agent-card.json": {
      "get": {
        "operationId": "getPublicAgentsByAddressAgentCardJson",
        "tags": [
          "Agent network"
        ],
        "summary": "Get a public agent’s A2A card",
        "description": "The A2A agent card (A2A 1.0), signed with our directory key (`signatures`, verifiable with `agent-keys.json`).",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/agents/{address}/keys.json": {
      "get": {
        "operationId": "getPublicAgentsByAddressKeysJson",
        "tags": [
          "Agent network"
        ],
        "summary": "Get a public agent’s keys",
        "description": "`{ keys: [jwk] }`: the keys the agent holds, with their status and dates, to verify its author signatures.",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/agents/{address}/oasf.json": {
      "get": {
        "operationId": "getPublicAgentsByAddressOasfJson",
        "tags": [
          "Agent network"
        ],
        "summary": "Get a public agent’s OASF record",
        "description": "The OASF record.",
        "security": [],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/public/handles/{workspace}/{agent}": {
      "get": {
        "operationId": "getPublicHandlesByWorkspaceByAgent",
        "tags": [
          "Agent network"
        ],
        "summary": "Resolve a public handle",
        "description": "`{ handle, address, card }` for a public listing; a renamed handle adds `redirected_from`.",
        "security": [],
        "parameters": [
          {
            "name": "workspace",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 40
            }
          },
          {
            "name": "agent",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 40
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/search": {
      "get": {
        "operationId": "getSearch",
        "tags": [
          "Search"
        ],
        "summary": "Search messages",
        "description": "Postgres full-text search with web-search syntax (`\"exact phrase\"`, `-exclude`, `or`), ranked, with a `snippet`.\n\nPermission: `search`.",
        "x-permission": "search",
        "parameters": [
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 500
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "agent",
                "email",
                "mixed"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "message",
                "task",
                "event"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup": {
      "post": {
        "operationId": "postSignup",
        "tags": [
          "Agent self-signup"
        ],
        "summary": "Sign up as an agent",
        "description": "No key. `{ challenge, solution, agent_name?, owner_email? }` → `201 { api_key, workspace, inbox, claim, restrictions, docs_url, next_steps }`. Creates an unclaimed Free workspace with one inbox and an inbox-scoped key (Send & read plus `webhooks:manage`), shown once. `agent_name` is one line of plain text. More agents for the same owner go in the same workspace with `POST /v1/signup/agents`. With `owner_email` we email that person a claim link. Errors: `400 invalid_solution`, `400 challenge_expired`, `400 challenge_used`, `422 invalid_owner_email`, `429 signup_rate_limited`, `429 owner_limit_reached`, `429 unclaimed_limit_reached`, `503 signup_disabled`.",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "challenge": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "solution": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 20
                  },
                  "agent_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "owner_email": {
                    "type": "string",
                    "maxLength": 254,
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "mailbox",
                      "identity"
                    ]
                  }
                },
                "required": [
                  "challenge",
                  "solution"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup/agents": {
      "post": {
        "operationId": "postSignupAgents",
        "tags": [
          "Agent self-signup"
        ],
        "summary": "Add another agent to an unclaimed workspace",
        "description": "`{ kind?: \"mailbox\" | \"identity\", expires_at? }` → `201 { api_key, api_key_expires_at, kind, workspace, inbox, identity, next_steps }`. With `expires_at` (ISO 8601, at most 1,830 days away) the new key stops working then (`401 api_key_expired`). Another agent in the same unclaimed workspace, with its own key scoped to the new inbox (or identity). Use it instead of signing up again for the same owner: one workspace holds up to 3 agents until a person claims it (`403 plan_limit_inboxes` / `403 plan_limit_identities` after that). Any key of the workspace (`inboxes:read`). `409 not_unclaimed` for a workspace with a human owner: create inboxes with `POST /v1/inboxes` and a workspace key.\n\nPermission: `inboxes:read`.",
        "x-permission": "inboxes:read",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "mailbox",
                      "identity"
                    ]
                  },
                  "expires_at": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date-time",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup/challenge": {
      "get": {
        "operationId": "getSignupChallenge",
        "tags": [
          "Agent self-signup"
        ],
        "summary": "Get a sign-up challenge",
        "description": "No key. `{ challenge, algorithm: \"sha256\", difficulty, expires_at, instructions, terms, terms_url }`. Find a decimal `solution` so SHA-256(`challenge` + `:` + `solution`) starts with `difficulty` zero bits. A challenge is valid 10 minutes and works once.",
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/signup/claim": {
      "post": {
        "operationId": "postSignupClaim",
        "tags": [
          "Agent self-signup"
        ],
        "summary": "Ask a person to claim the workspace",
        "description": "`{ email }` → `202 { status: \"email_sent\", email, expires_at }`. Emails a single-use claim link (72 hours) to a person. At most 3 a day. Needs `messages:send`. `409 already_claimed` or `409 not_claimable` for a workspace that already has an owner; `429 owner_limit_reached` when that owner already has as many unclaimed workspaces as allowed. `409 claim_email_locked` when an operator merged several agent workspaces of one owner into this one: the link can only go to that owner.\n\nPermission: `messages:send`.",
        "x-permission": "messages:send",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254,
                    "format": "email",
                    "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  }
                },
                "required": [
                  "email"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/stream": {
      "get": {
        "operationId": "getStream",
        "tags": [
          "Events"
        ],
        "summary": "Open the realtime event stream (WebSocket)",
        "description": "WebSocket (`wss://`). The webhook events, pushed live: `subscribe` with `inbox_ids?`, `event_types?`, `payload?` and `since?` to replay what you missed (last hour, up to 1000 events). Auth: `Authorization: Bearer` on the upgrade, or a stream token. Needs `messages:read`; without `drafts:read`, draft events arrive as envelopes. See [Realtime events](https://agentboxd.com/docs/realtime-events).\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/stream/token": {
      "post": {
        "operationId": "postStreamToken",
        "tags": [
          "Events"
        ],
        "summary": "Get a single-use stream URL",
        "description": "→ `201 { token, expires_at, url }`: a single-use URL for `GET /v1/stream`, valid 60 seconds, for browsers. Keys are never accepted in the URL.\n\nPermission: `messages:read`.",
        "x-permission": "messages:read",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/suppressions": {
      "get": {
        "operationId": "getSuppressions",
        "tags": [
          "Contacts"
        ],
        "summary": "List your suppressed addresses",
        "description": "`?reason=bounce|complaint|manual&q=&cursor=&limit=` → `{ data: [{ address, reason, created_at, expires_at }], next_cursor }`, newest first. Your workspace’s suppression list: addresses that bounced (`bounce`) or reported your mail as spam (`complaint`). Your sends to them are refused (`422 recipient_suppressed`). Only rows that apply now; other workspaces’ lists are never shown. `contacts:read`, workspace-wide keys only.\n\nPermission: `contacts:read`.",
        "x-permission": "contacts:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "bounce",
                "complaint",
                "manual"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 320
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/suppressions/{address}": {
      "delete": {
        "operationId": "deleteSuppressionsByAddress",
        "tags": [
          "Contacts"
        ],
        "summary": "Remove a suppressed address",
        "description": "Removes the address from your list, so you can write to it again → the removed row. A bounce or complaint needs `?confirm=true` (`409 confirmation_required` otherwise): sending again to an address that bounced or complained hurts your deliverability and can get sending paused. `404` when it isn’t on your list. Emits `suppression.removed` (who removed what). `contacts:write`, workspace-wide keys only.\n\nPermission: `contacts:write`.",
        "x-permission": "contacts:write",
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 3,
              "maxLength": 320
            }
          },
          {
            "name": "confirm",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/threads": {
      "get": {
        "operationId": "getThreads",
        "tags": [
          "Threads"
        ],
        "summary": "List threads across inboxes",
        "description": "Threads across every inbox the key can see (a supervisor’s view), newest activity first. Filters, all optional and combined: `inbox_id`, `labels` (comma-separated, all required), `before` / `after` (ISO time of the latest message), `participant` and `subject` (case-insensitive substrings), `ascending=true`, `include_blocked=true`, plus `limit` and `cursor`.\n\nPermission: `threads:read`.",
        "x-permission": "threads:read",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "labels",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 1000
            }
          },
          {
            "name": "before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            }
          },
          {
            "name": "participant",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 320
            }
          },
          {
            "name": "subject",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "ascending",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/threads/{id}": {
      "get": {
        "operationId": "getThreadsById",
        "tags": [
          "Threads"
        ],
        "summary": "Get a thread with its messages",
        "description": "The thread plus its messages in order. Threads carry `labels` and `metadata`. At most 200 messages: the newest ones, oldest first (`?limit=` for fewer). When there are older ones, `next_cursor` is set: pass it as `?cursor=` to get the page before.\n\nPermission: `threads:read`.",
        "x-permission": "threads:read",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "include_blocked",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200
            }
          },
          {
            "name": "include_unscreened",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          },
          {
            "name": "include_held",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchThreadsById",
        "tags": [
          "Threads"
        ],
        "summary": "Update a thread",
        "description": "`{ metadata?, add_labels?, remove_labels? }`. Metadata is merged; `null` deletes a key. At most 100 labels, as for messages (`400 too_many_labels`).\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "metadata": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[a-zA-Z0-9_.-]{1,64}$"
                    },
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string",
                          "maxLength": 1000
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "add_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  },
                  "remove_labels": {
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 64,
                      "pattern": "^[^\\s,]+$"
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteThreadsById",
        "tags": [
          "Threads"
        ],
        "summary": "Delete a thread",
        "description": "Deletes the thread with all its messages, attachments and extracted text, and the events that carry copies of them; their pending webhook deliveries are cancelled (`messages:write`). `{ deleted: true, messages, attachments }`. `409 message_sending` while a message in it is still going out; `503 storage_unavailable` if stored mail could not be removed (nothing is deleted then; try again).\n\nPermission: `messages:write`.",
        "x-permission": "messages:write",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "post": {
        "operationId": "postWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook",
        "description": "`{ url, events?, inbox_ids?, enabled?, secret?, payload?: \"full\" | \"envelope\", headers? }`. `url` must be a public HTTPS endpoint (`422 invalid_webhook_url` otherwise). `events` lists each event type at most once; repeats are dropped. `payload: \"full\"` sends message and draft content, so it needs the key’s `messages:read` for message and attachment events and `drafts:read` for draft events (`403 insufficient_permissions` otherwise). Without `payload`, a key that lacks them gets `envelope`. The secret is returned only here. `headers`: up to 10 extra headers sent with every delivery, e.g. `{ \"Authorization\": \"Bearer …\" }` for your own check next to the signature. Values are stored encrypted and never returned (webhooks show `header_names`); `Host`, `Content-Type` and our `X-Mailroom-*` headers can’t be set. On `PATCH`, `headers` replaces the set and `null` clears it. A workspace can have up to 20 webhooks (`409 webhook_limit_reached`); one webhook can take any number of event types and inboxes.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "events": {
                    "minItems": 1,
                    "maxItems": 41,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "message.received",
                        "message.sent",
                        "message.delivered",
                        "message.bounced",
                        "message.complained",
                        "message.enriched",
                        "message.released",
                        "inbox.expired",
                        "message.received.blocked",
                        "draft.created",
                        "draft.updated",
                        "draft.sent",
                        "draft.failed",
                        "draft.cancelled",
                        "identity.token_issued",
                        "identity.signed_in",
                        "signup.created",
                        "signup.claimed",
                        "attachment.extracted",
                        "attachment.extraction_failed",
                        "inbox.paused",
                        "inbox.resumed",
                        "domain.dkim_rotated",
                        "domain.dkim_rotation_due",
                        "domain.verified",
                        "domain.failed",
                        "connector.authorized",
                        "connector.revoked",
                        "workspace.stopped",
                        "workspace.resumed",
                        "escalation.sent",
                        "agent.updated",
                        "agent.revoked",
                        "agent.deleted",
                        "agent.reported",
                        "member.invited",
                        "member.invite_revoked",
                        "member.joined",
                        "member.role_changed",
                        "member.removed",
                        "suppression.removed"
                      ]
                    }
                  },
                  "inbox_ids": {
                    "anyOf": [
                      {
                        "minItems": 1,
                        "maxItems": 1000,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "secret": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 256
                  },
                  "payload": {
                    "type": "string",
                    "enum": [
                      "full",
                      "envelope"
                    ]
                  },
                  "headers": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[A-Za-z0-9][A-Za-z0-9-]{0,63}$"
                    },
                    "additionalProperties": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 1024,
                      "pattern": "^[^\\r\\n]*$"
                    }
                  }
                },
                "required": [
                  "url"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "getWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhooks",
        "description": "Returns `secret_hint`, never the secret, and `stats`: `deliveries_24h`, `failed_24h`, `error_rate_24h`, `last_success_at`, `last_failure_at`.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "get": {
        "operationId": "getWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Get a webhook",
        "description": "Returns `secret_hint`, never the secret, and `stats`: `deliveries_24h`, `failed_24h`, `error_rate_24h`, `last_success_at`, `last_failure_at`.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "patchWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook",
        "description": "Change events, scope, `payload` or `enabled`; delete. Moving a full-payload webhook to another `url`, switching it to `full` or adding events needs the same permissions as creating it.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "events": {
                    "minItems": 1,
                    "maxItems": 41,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "message.received",
                        "message.sent",
                        "message.delivered",
                        "message.bounced",
                        "message.complained",
                        "message.enriched",
                        "message.released",
                        "inbox.expired",
                        "message.received.blocked",
                        "draft.created",
                        "draft.updated",
                        "draft.sent",
                        "draft.failed",
                        "draft.cancelled",
                        "identity.token_issued",
                        "identity.signed_in",
                        "signup.created",
                        "signup.claimed",
                        "attachment.extracted",
                        "attachment.extraction_failed",
                        "inbox.paused",
                        "inbox.resumed",
                        "domain.dkim_rotated",
                        "domain.dkim_rotation_due",
                        "domain.verified",
                        "domain.failed",
                        "connector.authorized",
                        "connector.revoked",
                        "workspace.stopped",
                        "workspace.resumed",
                        "escalation.sent",
                        "agent.updated",
                        "agent.revoked",
                        "agent.deleted",
                        "agent.reported",
                        "member.invited",
                        "member.invite_revoked",
                        "member.joined",
                        "member.role_changed",
                        "member.removed",
                        "suppression.removed"
                      ]
                    }
                  },
                  "inbox_ids": {
                    "anyOf": [
                      {
                        "minItems": 1,
                        "maxItems": 1000,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "format": "uuid",
                          "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "payload": {
                    "type": "string",
                    "enum": [
                      "full",
                      "envelope"
                    ]
                  },
                  "headers": {
                    "anyOf": [
                      {
                        "type": "object",
                        "propertyNames": {
                          "type": "string",
                          "pattern": "^[A-Za-z0-9][A-Za-z0-9-]{0,63}$"
                        },
                        "additionalProperties": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 1024,
                          "pattern": "^[^\\r\\n]*$"
                        }
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhooksById",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook",
        "description": "Change events, scope, `payload` or `enabled`; delete. Moving a full-payload webhook to another `url`, switching it to `full` or adding events needs the same permissions as creating it.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "getWebhooksByIdDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "List a webhook’s deliveries",
        "description": "`?status=pending|succeeded|failed&cursor=&limit=`, newest first: `{ data: [{ id, event_id, event_type, status, attempts, last_status_code, last_error, last_response_ms, next_attempt_at, last_attempt_at, redelivered_at, created_at }], next_cursor }`. Each row is one event sent to this webhook; `attempts` is the number of its latest attempt, `last_response_ms` how long that attempt took. Deliveries are kept as long as their event (message, attachment, draft and agent events follow your retention).\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "default": 25,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "succeeded",
                "failed"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver": {
      "post": {
        "operationId": "postWebhooksByIdDeliveriesByDeliveryIdRedeliver",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a delivery again",
        "description": "Sends that delivery again: the same payload, signed again with a fresh timestamp, one attempt (no retries) → `202` with the delivery, `status: \"pending\"`. `409 delivery_pending` while it is still being retried, `409 webhook_disabled` while the webhook is paused, `404` when it isn’t this webhook’s.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/redeliver": {
      "post": {
        "operationId": "postWebhooksByIdRedeliver",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send an event again, by event id",
        "description": "`{ event_id }`: the same, found by event id.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "event_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "event_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/rotate-secret": {
      "post": {
        "operationId": "postWebhooksByIdRotateSecret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate a webhook’s signing secret",
        "description": "`{ secret? }`: replaces the signing secret with yours (16–256 characters) or a generated one, and returns it once. See [Rotate the secret](https://agentboxd.com/docs/webhooks#rotate-the-secret).\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "secret": {
                    "type": "string",
                    "minLength": 16,
                    "maxLength": 256
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "postWebhooksByIdTest",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Sends a `webhook.test` event.\n\nPermission: `webhooks:manage`.",
        "x-permission": "webhooks:manage",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/events": {
      "get": {
        "operationId": "getWebhooksEvents",
        "tags": [
          "Webhooks"
        ],
        "summary": "List event types",
        "description": "Public. Every event type with a description and an example payload. Webhooks accept `payload: \"envelope\"` for ids, addresses, subject and labels only: no bodies or AI content.",
        "security": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "4XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "5XX": {
            "description": "Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "An API key (`mr_…`), scoped to the workspace or one inbox, with a set of permissions."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "Stable, machine-readable error code."
              },
              "message": {
                "type": "string",
                "description": "What happened and how to fix it, in plain words."
              },
              "details": {
                "description": "The specifics: which recipient, which limit, until when."
              },
              "docs_url": {
                "type": "string",
                "format": "uri",
                "description": "For a refused send: its entry on \"Why was my send refused?\" (https://agentboxd.com/docs/send-refusals)."
              }
            }
          }
        }
      }
    }
  }
}
