{
  "openapi": "3.1.0",
  "info": {
    "title": "Kobana Autonomous Inbox API",
    "version": "1.2.0",
    "description": "API REST pública do Inbox Autônomo Kobana.\n\nAutenticação: Bearer JWT (RS256, emitido pelo Authorization Server da Kobana; `aud` inclui `https://api.inbox[.<env>].kobana.com.br`) somado a mTLS terminado no CloudFront (repassado como o header `cloudfront-viewer-mtls-client-cert-fingerprint`). O claim `org` do JWT (a conta Kobana) resolve a organização do chamador; `sub` é a pessoa e é carregado só para atribuição. Escolha um workspace dentro da organização com `X-Workspace-Id` quando houver mais de um.\n\nOs endpoints de recurso `{id}` (workspaces, inboxes, agents, webhooks) aceitam tanto o UUID interno quanto o `external_id` do recurso. Endpoints POST que possuem `external_id` o aceitam como campo opcional, usando por padrão o `id` interno gerado quando omitido. O campo `deleted_at` nunca é retornado nas respostas nem nos payloads de webhook; registros com soft-delete são filtrados em vez disso.\n\nTodas as chaves nas respostas e nos payloads de webhook estão em `snake_case`. As entregas de webhook compartilham o serializador da API: o envelope traz `event` (`slug`, `id`), `delivered_at` e `workspace`; `data` aninha snapshots dos recursos (`organization`, `agent`, `inbox`, `email`, `agent_run`) mais as chaves específicas do evento."
  },
  "servers": [
    {
      "url": "https://api.inbox.kobana.com.br",
      "description": "Produção"
    },
    {
      "url": "https://api.inbox.sandbox.kobana.com.br",
      "description": "Sandbox"
    },
    {
      "url": "http://localhost:3028/api",
      "description": "Desenvolvimento local"
    }
  ],
  "tags": [
    {
      "name": "Workspaces"
    },
    {
      "name": "Inboxes"
    },
    {
      "name": "Emails"
    },
    {
      "name": "Agents"
    },
    {
      "name": "Agent runs"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Webhook deliveries"
    },
    {
      "name": "System events"
    },
    {
      "name": "Secrets"
    },
    {
      "name": "Workflow runs"
    },
    {
      "name": "Usage"
    },
    {
      "name": "LLM models"
    },
    {
      "name": "Identity"
    }
  ],
  "paths": {
    "/v1/workspaces": {
      "get": {
        "operationId": "list-workspaces",
        "summary": "Listar workspaces",
        "description": "Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo. Paginação keyset com filtros tipados.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`, `slug`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `source[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "slug",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `slug[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `external_id[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Workspace"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-workspace",
        "summary": "Criar workspace",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkspaceCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Exige token `src=system`. O workspace é criado dentro da organização do token. Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo."
      },
      "put": {
        "operationId": "upsert-workspace",
        "summary": "Criar ou atualizar workspace",
        "description": "Upsert. Recebe o mesmo corpo do POST mais as chaves de busca `id` e `external_id`, casadas nessa ordem. Um match é atualizado in place e responde 200 — campos ausentes do corpo mantêm o valor armazenado. Sem chave, ou sem match, cria o workspace exatamente como o POST faria e responde 201. Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo. Exige token `src=system`; `external_id` não pode ser alterado em um workspace casado (409).",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkspaceUpsert"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workspaces/{id}": {
      "get": {
        "operationId": "get-workspace",
        "summary": "Obter workspace",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso. Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update-workspace",
        "summary": "Atualizar workspace",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso. Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo. Alterar `monthly_cost_limit` / `monthly_emails_limit` exige token `src=system`.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WorkspaceUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Workspace"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-workspace",
        "summary": "Excluir workspace",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso. Escopo: a organização do workspace do token — todo workspace vivo dessa organização é alcançável; um fora dela é 404. Um token cujo workspace não tem organização enxerga só a si mesmo. Exige token `src=system`.",
        "tags": [
          "Workspaces"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workspaces",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sem conteúdo."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes": {
      "get": {
        "operationId": "list-inboxes",
        "summary": "Listar inboxes",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`, `slug`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "inactive"
              ]
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `agent_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "slug",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `slug[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `email[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `external_id[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Inbox"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-inbox",
        "summary": "Criar inbox",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InboxCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Inbox"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "upsert-inbox",
        "summary": "Criar ou atualizar caixa",
        "description": "Upsert. Recebe o mesmo corpo do POST mais as chaves de busca `id` e `external_id`, casadas nessa ordem, depois por `email`. Um match é atualizado in place e responde 200 — campos ausentes do corpo mantêm o valor armazenado. Sem chave, ou sem match, cria a caixa exatamente como o POST faria e responde 201.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InboxUpsert"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Inbox"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Inbox"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}": {
      "get": {
        "operationId": "get-inbox",
        "summary": "Obter inbox",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Inbox"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update-inbox",
        "summary": "Atualizar inbox",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InboxUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Inbox"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-inbox",
        "summary": "Excluir inbox",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sem conteúdo."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/agents": {
      "get": {
        "operationId": "list-agents",
        "summary": "Listar agents",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`, `version`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "llm_model",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `llm_model[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `external_id[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agent"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-agent",
        "summary": "Criar agent",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "upsert-agent",
        "summary": "Criar ou atualizar agente",
        "description": "Upsert. Recebe o mesmo corpo do POST mais as chaves de busca `id` e `external_id`, casadas nessa ordem. Um match é atualizado in place e responde 200 — campos ausentes do corpo mantêm o valor armazenado. Sem chave, ou sem match, cria o agente exatamente como o POST faria e responde 201.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentUpsert"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/agents/{id}": {
      "get": {
        "operationId": "get-agent",
        "summary": "Obter agent",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update-agent",
        "summary": "Atualizar agent",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Agent"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-agent",
        "summary": "Excluir agent",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sem conteúdo."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks": {
      "get": {
        "operationId": "list-webhooks",
        "summary": "Listar webhooks",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "inactive"
              ]
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `inbox_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `external_id[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-webhook",
        "summary": "Criar webhook",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "upsert-webhook",
        "summary": "Criar ou atualizar webhook",
        "description": "Upsert. Recebe o mesmo corpo do POST mais as chaves de busca `id` e `external_id`, casadas nessa ordem. Um match é atualizado in place e responde 200 — campos ausentes do corpo mantêm o valor armazenado. Sem chave, ou sem match, cria o webhook exatamente como o POST faria e responde 201.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpsert"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}": {
      "get": {
        "operationId": "get-webhook",
        "summary": "Obter webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update-webhook",
        "summary": "Atualizar webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-webhook",
        "summary": "Excluir webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sem conteúdo."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/secrets": {
      "get": {
        "operationId": "list-secrets",
        "summary": "Listar secrets",
        "description": "Paginação por keyset. Os filtros são query params tipados (`campo=valor`, `campo[op]=valor`). O valor de um secret nunca é devolvido por nenhum endpoint: ele é guardado criptografado e só é lido pelo executor de workflows. Para rotacioná-lo, faça `PATCH` na linha (ou `PUT` por `key`) com um novo `value`.",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "key",
            "in": "query",
            "required": false,
            "description": "Equality. Also `key[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Secret"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Opaque keyset cursor for the next page; `null` on the last page."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-secret",
        "summary": "Criar secret",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Secret"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "description": "Guarda um secret que um workflow do agente pode referenciar como `${{secrets.KEY}}`. Uma `key` duplicada no workspace é recusada com 409 `conflict`. O valor é somente escrita: guardado criptografado e nunca devolvido."
      },
      "put": {
        "operationId": "upsert-secret",
        "summary": "Criar ou atualizar secret",
        "description": "Upsert casado por `key` dentro do workspace de quem chama — o caminho da rotação, sem precisar buscar o id. Cria com 201 quando a chave é nova, substitui o valor com 200 quando já existe. O valor é somente escrita.",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretUpsert"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Secret"
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Secret"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/secrets/{id}": {
      "get": {
        "operationId": "get-secret",
        "summary": "Obter secret",
        "description": "Accepts either the internal UUID or the resource `external_id`.",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Secret"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "update-secret",
        "summary": "Atualizar secret",
        "description": "Substitui o valor ou as notas. `key` é imutável: os workflows a referenciam pelo nome, então renomeá-la os quebraria silenciosamente — exclua e crie de novo.",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SecretUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Secret"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Restrição de unicidade violada (ex.: `external_id` ou `email` da inbox já em uso).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação do corpo que requer contexto do lado do servidor (ex.: domínio da inbox incompatível).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-secret",
        "summary": "Excluir secret",
        "description": "Soft delete. Passos de workflow que referenciam a chave passam a falhar com `secret not defined` a partir da próxima execução.",
        "tags": [
          "Secrets"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/secrets",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No content."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workflow-runs": {
      "get": {
        "operationId": "list-workflow-runs",
        "summary": "Listar execuções de workflow",
        "description": "Paginação por keyset. Os filtros são query params tipados (`campo=valor`, `campo[op]=valor`). Os passos não vêm embutidos na listagem — `GET /v1/workflow-runs/{id}` os devolve.",
        "tags": [
          "Workflow runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workflow_runs"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `label`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "running",
                "success",
                "failed"
              ]
            }
          },
          {
            "name": "email_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `email_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `inbox_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `agent_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "agent_run_id",
            "in": "query",
            "required": false,
            "description": "Equality. Also `agent_run_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `finished_at[in]=a,b` e `finished_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page of results.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WorkflowRun"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Opaque keyset cursor for the next page; `null` on the last page."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/workflow-runs/{id}": {
      "get": {
        "operationId": "get-workflow-run",
        "summary": "Obter execução de workflow",
        "description": "A execução com todos os passos na ordem de execução. Requisições e respostas são guardadas com os valores de secrets substituídos por `[REDACTED]`; os corpos são truncados em 4000 caracteres.",
        "tags": [
          "Workflow runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/workflow_runs"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkflowRun"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails": {
      "get": {
        "operationId": "list-emails",
        "summary": "Listar emails",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `from`, `status`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "received",
                "approved",
                "rejected",
                "processing",
                "processed",
                "failed"
              ]
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `inbox_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `agent_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "message_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `message_id[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `from[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Linhas cujo `to` contém o valor.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `updated_at[in]=a,b` e `updated_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "updated_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "received_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `received_at[in]=a,b` e `received_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "received_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "received_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "processed_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `processed_at[in]=a,b` e `processed_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "processed_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "processed_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Email"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "create-email",
        "summary": "Enviar um .eml bruto",
        "description": "Armazena uma mensagem RFC 5322 exatamente como a ingestão SES faria: objeto bruto no bucket raw, `Email` em `received` e um job `process-email` — filtros, agente e webhooks rodam como para um e-mail real. Envie a mensagem como `multipart/form-data` (campo `file`, `inbox_id` opcional) ou como corpo da requisição com `Content-Type: message/rfc822` (`?inbox_id=` opcional). Sem `inbox_id`, a caixa é resolvida pelo cabeçalho `To:` entre as caixas do workspace do token. Um `Message-ID` já armazenado é rejeitado com 409 (`error.details.email_id` aponta para o e-mail existente).",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Caixa de destino. Sobrescrito pelo campo multipart `inbox_id` quando ambos são enviados.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "message/rfc822": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "O arquivo `.eml` (máx. 20 MB)."
                  },
                  "inbox_id": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Armazenado e enfileirado para processamento.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "queued"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Email"
                    },
                    "queued": {
                      "type": "boolean",
                      "description": "`false` quando a linha foi armazenada mas o job de processamento não pôde ser enfileirado; reprocesse depois."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Corpo vazio ou campo multipart `file` ausente.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`inbox_id` não existe no workspace do token (`inbox_not_found`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`duplicate_message_id`: o `Message-ID` já está armazenado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "`payload_too_large`: mensagem acima de 20 MB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "415": {
            "description": "`unsupported_media_type`: o corpo não é multipart nem `message/rfc822`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "`no_inbox_matches_to_header` (nenhuma caixa do workspace corresponde aos destinatários do `To:`) ou `missing_recipient` (sem cabeçalho `To:` utilizável; informe `inbox_id`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/{id}": {
      "get": {
        "operationId": "get-email",
        "summary": "Obter email",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Email"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "delete-email",
        "summary": "Excluir e-mail",
        "description": "Soft-delete do e-mail (define `deleted_at`). Ele deixa de aparecer em listagens e detalhe; o objeto bruto é purgado pelo job de retenção.",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Sem conteúdo."
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/{id}/eml": {
      "get": {
        "operationId": "download-original-eml",
        "summary": "Baixar o .eml original",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Fluxo bruto da mensagem no formato RFC 5322.",
            "content": {
              "message/rfc822": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/emails/{id}/reprocess": {
      "post": {
        "operationId": "reprocess-email",
        "summary": "Reprocessar email",
        "description": "Reenfileira o processamento do email independentemente do status atual.",
        "tags": [
          "Emails"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/emails"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Aceito e enfileirado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "required": [
                        "email_id",
                        "queued"
                      ],
                      "properties": {
                        "email_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "queued": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage/summary": {
      "get": {
        "operationId": "get-usage-summary",
        "summary": "Resumo de uso",
        "description": "E-mails processados, tokens e custo por dia UTC no período (somente execuções de agente com sucesso), mais os contadores mensais correntes versus os limites do workspace. Custo em USD, como faturado pelo AI Gateway.",
        "tags": [
          "Usage"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/usage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Primeiro dia UTC, `YYYY-MM-DD`. Padrão: 29 dias antes de `to`.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Último dia UTC (inclusive), `YYYY-MM-DD`. Padrão: hoje.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageSummary"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/usage/cost": {
      "get": {
        "operationId": "get-usage-cost",
        "summary": "Custo por modelo",
        "description": "Custo e tokens por modelo LLM no período: totais por modelo e série diária.",
        "tags": [
          "Usage"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/usage"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Primeiro dia UTC, `YYYY-MM-DD`. Padrão: 29 dias antes de `to`.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Último dia UTC (inclusive), `YYYY-MM-DD`. Padrão: hoje.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/UsageCost"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "operationId": "list-models",
        "summary": "Listar modelos LLM disponíveis",
        "description": "Modelos aceitos em `Agent.llm_model`, com preço por token: o catálogo do AI Gateway restrito aos modelos que têm preço, de modo que todo modelo listado é custeado e contado contra o limite do workspace.",
        "tags": [
          "LLM models"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Catálogo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Model"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`gateway_error`: não foi possível obter o catálogo do AI Gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/agents/{id}/versions": {
      "get": {
        "operationId": "list-agent-versions",
        "summary": "Listar versões do prompt do agente",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Agents"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agents"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `version`. Padrão `-version`.",
            "schema": {
              "type": "string",
              "default": "-version"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `version[in]=a,b` e `version[gt|gte|lt|lte]`.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "version[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "version[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentVersion"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/agent-runs": {
      "get": {
        "operationId": "list-agent-runs",
        "summary": "Listar agent runs",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "Agent runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agent_runs"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `updated_at`, `total_cost`, `status`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "running",
                "success",
                "failed"
              ]
            }
          },
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `agent_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "email_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `email_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `inbox_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "llm_model",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `llm_model[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `finished_at[in]=a,b` e `finished_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "finished_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "total_cost",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `total_cost[in]=a,b` e `total_cost[gt|gte|lt|lte]`.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "total_cost[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "total_cost[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AgentRun"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/agent-runs/{id}": {
      "get": {
        "operationId": "get-agent-run",
        "summary": "Obter agent run",
        "tags": [
          "Agent runs"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/agent_runs"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/AgentRun"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/inboxes/{id}/recipients": {
      "post": {
        "operationId": "add-allowed-recipient",
        "summary": "Adicionar destinatário permitido",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso. Adiciona um email a `allowed_recipients`. Idempotente — retorna 200 com a lista atual quando o item já está presente.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Destinatário já presente (nenhuma ação realizada).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "allowed_recipients": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "email"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "201": {
            "description": "Destinatário adicionado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "allowed_recipients": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "email"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remove-allowed-recipient",
        "summary": "Remover destinatário permitido",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso. Remove um email de `allowed_recipients`. Aceita o email no corpo JSON ou como o parâmetro de query `email`.",
        "tags": [
          "Inboxes"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/inboxes",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "email"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Destinatário removido.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "allowed_recipients": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "format": "email"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/test": {
      "post": {
        "operationId": "send-a-webhook-test-event",
        "summary": "Enviar um evento webhook.ping",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Aceito e enfileirado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "required": [
                        "webhook_id",
                        "event_id",
                        "queued"
                      ],
                      "properties": {
                        "webhook_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "event_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "queued": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/regenerate-secret": {
      "post": {
        "operationId": "regenerate-the-signing-secret",
        "summary": "Rotacionar o signing secret",
        "description": "Substitui o signing secret e retorna o novo valor **uma única vez**. Por padrão o secret anterior continua assinando entregas por 24 horas (`previous_secret_grace_hours`), período em que cada entrega carrega uma assinatura por secret, para que o receptor troque a chave sem perder eventos. Informe `0` para revogar o secret anterior imediatamente (secret vazado). Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhooks"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Opcional. 8-255 caracteres de [A-Za-z0-9_-:.]. Um replay com a mesma chave em 24h devolve a resposta original; a mesma chave com corpo diferente devolve 409 `conflict`.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 255
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "signing_secret": {
                    "type": "string",
                    "pattern": "^whsec_[A-Za-z0-9+/]+={0,2}$",
                    "description": "Opcional. Traga seu próprio signing secret: `whsec_` + base64 padrão de 24-64 bytes aleatórios. Gerado (32 bytes) quando omitido. Retornado em texto claro somente nesta resposta."
                  },
                  "previous_secret_grace_hours": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 168,
                    "default": 24,
                    "description": "Horas em que o secret anterior permanece válido após a rotação. `0` revoga imediatamente."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Novo signing secret (exibido uma única vez).",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "signing_secret",
                    "previous_secret_expires_at"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Webhook"
                    },
                    "signing_secret": {
                      "type": "string",
                      "example": "whsec_..."
                    },
                    "previous_secret_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Quando o secret anterior deixa de assinar; `null` se revogado imediatamente."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries": {
      "get": {
        "operationId": "list-webhook-deliveries",
        "summary": "Listar entregas de webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhook deliveries"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `attempt`, `status`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `status[in]=a,b`.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "success",
                "failed"
              ]
            }
          },
          {
            "name": "attempt",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `attempt[in]=a,b` e `attempt[gt|gte|lt|lte]`.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "attempt[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "attempt[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "response_status",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `response_status[in]=a,b` e `response_status[gt|gte|lt|lte]`.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "response_status[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "response_status[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "system_event_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `system_event_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "delivered_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `delivered_at[in]=a,b` e `delivered_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "delivered_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "delivered_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries/{deliveryId}": {
      "get": {
        "operationId": "get-webhook-delivery",
        "summary": "Obter entrega de webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhook deliveries"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebhookDelivery"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/webhooks/{id}/deliveries/{deliveryId}/replay": {
      "post": {
        "operationId": "replay-a-webhook-delivery",
        "summary": "Reenviar (replay) uma entrega de webhook",
        "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
        "tags": [
          "Webhook deliveries"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/webhooks",
              "write"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          },
          {
            "name": "deliveryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Aceito e enfileirado.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "type": "object",
                      "required": [
                        "webhook_id",
                        "delivery_id",
                        "system_event_id",
                        "queued"
                      ],
                      "properties": {
                        "webhook_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "delivery_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "system_event_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "queued": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system-events": {
      "get": {
        "operationId": "list-system-events",
        "summary": "Listar system events",
        "description": "Paginação keyset. Filtros são query params tipados (`campo=valor`, `campo[op]=valor`); filtros desconhecidos, campos não ordenáveis e valores malformados são rejeitados com 400 `validation_failed`.",
        "tags": [
          "System events"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/system_events"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Cursor opaco retornado em `meta.next_cursor` da página anterior.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Chaves de ordenação separadas por vírgula, prefixo `-` para decrescente. Permitidas: `created_at`, `slug`. Padrão `-created_at`.",
            "schema": {
              "type": "string",
              "default": "-created_at"
            }
          },
          {
            "name": "slug",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `slug[in]=a,b`.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inbox_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `inbox_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "email_id",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `email_id[in]=a,b`.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "created_at",
            "in": "query",
            "required": false,
            "description": "Igualdade. Também `created_at[in]=a,b` e `created_at[gt|gte|lt|lte]`.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[gte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_at[lte]",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Página de resultados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "meta"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SystemEvent"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "required": [
                        "next_cursor"
                      ],
                      "properties": {
                        "next_cursor": {
                          "type": "string",
                          "nullable": true,
                          "description": "Cursor keyset opaco da próxima página; `null` na última página."
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "O corpo falhou na validação Zod. `error.details` carrega `formErrors`/`fieldErrors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/system-events/{id}": {
      "get": {
        "operationId": "get-system-event",
        "summary": "Obter system event",
        "tags": [
          "System events"
        ],
        "security": [
          {
            "bearerAuth": [
              "inbox/system_events"
            ]
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "Fingerprint mTLS. Em produção o CloudFront o injeta a partir do mTLS do viewer.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Segredo compartilhado entre o CloudFront e a origem. Obrigatório em produção; ignorado em desenvolvimento a menos que `CF_ORIGIN_SHARED_SECRET` esteja definido.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Aceita tanto o UUID interno quanto o `external_id` do recurso.",
            "schema": {
              "type": "string",
              "minLength": 1
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SystemEvent"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas o escopo é insuficiente ou o recurso está fora de alcance.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso não encontrado ou filtrado por soft-delete.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/me": {
      "get": {
        "operationId": "get-me",
        "summary": "Identidade por trás do token",
        "description": "Quem o token Bearer representa: a pessoa (`null` para um token de máquina), a organização e o alcance do próprio token. Use para testar se um token configurado é válido. Não exige escopo de recurso: qualquer token que seja verificado recebe resposta. O token em si nunca é devolvido.",
        "tags": [
          "Identity"
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "name": "cloudfront-viewer-mtls-client-cert-fingerprint",
            "in": "header",
            "required": true,
            "description": "mTLS fingerprint. In production CloudFront injects it from viewer mTLS.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-origin-shared-secret",
            "in": "header",
            "required": false,
            "description": "Shared secret between CloudFront and the origin. Required in production; ignored in development unless `CF_ORIGIN_SHARED_SECRET` is set.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Identidade.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Falha de autenticação (JWT ou mTLS ausente/inválido).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Autenticado, mas a organização ou o vínculo do token é desconhecido aqui.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "example": "validation_failed"
              },
              "message": {
                "type": "string"
              },
              "details": {}
            }
          }
        }
      },
      "Workspace": {
        "type": "object",
        "description": "Workspace conforme retornado pela API. `deleted_at` é omitido das respostas.",
        "required": [
          "id",
          "external_id",
          "source",
          "label",
          "slug"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_id": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "$ref": "#/components/schemas/WorkspaceSource"
          },
          "label": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "description": "Segmento do meio de todo endereço de caixa deste workspace: \"{organization-slug}.{workspace-slug}.{inbox-slug}@inbox.kobana.com.br\" (o segmento da organização é omitido quando o workspace não tem uma). Único dentro da organização. Padrão: o label em formato dasherized."
          },
          "monthly_cost_limit": {
            "type": "number",
            "nullable": true
          },
          "monthly_cost_used": {
            "type": "number"
          },
          "monthly_emails_limit": {
            "type": "integer",
            "nullable": true
          },
          "monthly_emails_used": {
            "type": "integer"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados de sistema, escritos pela Kobana. Somente leitura."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Graváveis por esta API."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WorkspaceSource": {
        "type": "string",
        "enum": [
          "kobana_app",
          "kobana_billing",
          "kobana_inbox",
          "kobana_agent",
          "kobana_finance",
          "kobana_legal",
          "kobana_team"
        ]
      },
      "WorkspaceCreate": {
        "type": "object",
        "required": [
          "source",
          "label"
        ],
        "properties": {
          "external_id": {
            "type": "string",
            "minLength": 1,
            "description": "Opcional. Quando omitido, o servidor usa por padrão o `id` interno gerado como `external_id`."
          },
          "source": {
            "$ref": "#/components/schemas/WorkspaceSource"
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "description": "Opcional. Slug minúsculo e dasherized, único dentro da organização, usado como segmento do meio dos endereços de caixa. Limitado a 20 caracteres para que a parte local composta caiba no limite SMTP de 64 caracteres. Quando omitido, o servidor deriva do `label` dasherized."
          },
          "monthly_cost_limit": {
            "type": "number",
            "nullable": true,
            "exclusiveMinimum": 0
          },
          "monthly_emails_limit": {
            "type": "integer",
            "nullable": true,
            "exclusiveMinimum": 0
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          }
        }
      },
      "WorkspaceUpdate": {
        "type": "object",
        "required": [],
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
          },
          "monthly_cost_limit": {
            "type": "number",
            "nullable": true,
            "exclusiveMinimum": 0
          },
          "monthly_emails_limit": {
            "type": "integer",
            "nullable": true,
            "exclusiveMinimum": 0
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          },
          "custom_metadata_mode": {
            "type": "string",
            "enum": [
              "replace",
              "merge"
            ],
            "default": "replace",
            "description": "Como o `custom_metadata` enviado é reconciliado com o valor armazenado. `replace` (padrão) sobrescreve o objeto inteiro; `merge` faz deep-merge sobre o valor atual — objetos aninhados mesclam recursivamente, escalares e arrays sobrescrevem a chave, e chaves `null` são mantidas (não apagam a chave). Somente em update."
          }
        }
      },
      "Inbox": {
        "type": "object",
        "required": [
          "id",
          "external_id",
          "workspace_id",
          "label",
          "slug",
          "email",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_id": {
            "type": "string",
            "nullable": true
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "label": {
            "type": "string"
          },
          "slug": {
            "type": "string",
            "description": "Último segmento do endereço, único dentro do workspace. Congelado após a criação: renomear um slug nunca redireciona um endereço já entregue."
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "allowed_recipients": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "filters": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "attachments_allow": {
            "type": "boolean"
          },
          "attachments_max_file_number": {
            "type": "integer"
          },
          "attachments_max_file_size": {
            "type": "integer"
          },
          "attachments_max_total_size": {
            "type": "integer"
          },
          "attachments_allow_rules": {
            "type": "array",
            "nullable": true,
            "maxItems": 20,
            "description": "Lista de anexos permitidos. Um anexo é processado quando atende a pelo menos uma regra; dentro de uma regra, todas as condições informadas precisam ser atendidas. `null` ou `[]` processa todos os anexos. Um anexo fora da lista é ignorado, nunca um motivo para rejeitar o e-mail: o agente não o vê, os limites de anexos não o contam e um passo de workflow não pode referenciá-lo. No update, omita para manter e envie `null` para limpar.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "extensions": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 50,
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9]{1,16}$"
                  },
                  "description": "Extensões sem o ponto, sem diferenciar maiúsculas, ex.: `[\"pdf\", \"xml\"]`."
                },
                "filename_pattern": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Expressão regular JavaScript testada contra o nome do arquivo, ex.: `^GUIA_`. Quantificadores aninhados são recusados. Um anexo sem nome nunca é atendido."
                },
                "case_sensitive": {
                  "type": "boolean",
                  "description": "Vale para `filename_pattern`. Padrão false."
                }
              }
            }
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados de sistema, escritos pela Kobana. Somente leitura."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Graváveis por esta API."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "InboxCreate": {
        "type": "object",
        "required": [
          "label"
        ],
        "properties": {
          "external_id": {
            "type": "string",
            "minLength": 1,
            "description": "Opcional. Usa por padrão o `id` interno gerado."
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Opcional. Deve usar o domínio de caixa configurado (`SES_DOMAIN`); caso contrário retorna 422. Endereços duplicados retornam 409. Quando omitido, o servidor compõe como \"{organization-slug}.{workspace-slug}.{inbox-slug}@<domain>\"."
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "description": "Opcional. Slug minúsculo e dasherized, único dentro do workspace, usado como último segmento do endereço. Retorna 409 quando colide com outra caixa do mesmo workspace e 422 quando a parte local composta excede 64 caracteres. Quando omitido, o servidor deriva do `label` dasherized."
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "allowed_recipients": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "filters": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "attachments_allow": {
            "type": "boolean"
          },
          "attachments_max_file_number": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_max_file_size": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_max_total_size": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_allow_rules": {
            "type": "array",
            "nullable": true,
            "maxItems": 20,
            "description": "Lista de anexos permitidos. Um anexo é processado quando atende a pelo menos uma regra; dentro de uma regra, todas as condições informadas precisam ser atendidas. `null` ou `[]` processa todos os anexos. Um anexo fora da lista é ignorado, nunca um motivo para rejeitar o e-mail: o agente não o vê, os limites de anexos não o contam e um passo de workflow não pode referenciá-lo. No update, omita para manter e envie `null` para limpar.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "extensions": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 50,
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9]{1,16}$"
                  },
                  "description": "Extensões sem o ponto, sem diferenciar maiúsculas, ex.: `[\"pdf\", \"xml\"]`."
                },
                "filename_pattern": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Expressão regular JavaScript testada contra o nome do arquivo, ex.: `^GUIA_`. Quantificadores aninhados são recusados. Um anexo sem nome nunca é atendido."
                },
                "case_sensitive": {
                  "type": "boolean",
                  "description": "Vale para `filename_pattern`. Padrão false."
                }
              }
            }
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          }
        }
      },
      "InboxUpdate": {
        "type": "object",
        "required": [],
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "description": "Alterar isto recompõe o endereço de recebimento a partir da cadeia de slugs — e-mails enviados ao endereço anterior deixam de chegar. Retorna 409 em colisão dentro do workspace e 422 quando a parte local composta excede 64 caracteres."
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "allowed_recipients": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "filters": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "attachments_allow": {
            "type": "boolean"
          },
          "attachments_max_file_number": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_max_file_size": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_max_total_size": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "attachments_allow_rules": {
            "type": "array",
            "nullable": true,
            "maxItems": 20,
            "description": "Lista de anexos permitidos. Um anexo é processado quando atende a pelo menos uma regra; dentro de uma regra, todas as condições informadas precisam ser atendidas. `null` ou `[]` processa todos os anexos. Um anexo fora da lista é ignorado, nunca um motivo para rejeitar o e-mail: o agente não o vê, os limites de anexos não o contam e um passo de workflow não pode referenciá-lo. No update, omita para manter e envie `null` para limpar.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "extensions": {
                  "type": "array",
                  "minItems": 1,
                  "maxItems": 50,
                  "items": {
                    "type": "string",
                    "pattern": "^[A-Za-z0-9]{1,16}$"
                  },
                  "description": "Extensões sem o ponto, sem diferenciar maiúsculas, ex.: `[\"pdf\", \"xml\"]`."
                },
                "filename_pattern": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Expressão regular JavaScript testada contra o nome do arquivo, ex.: `^GUIA_`. Quantificadores aninhados são recusados. Um anexo sem nome nunca é atendido."
                },
                "case_sensitive": {
                  "type": "boolean",
                  "description": "Vale para `filename_pattern`. Padrão false."
                }
              }
            }
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          },
          "custom_metadata_mode": {
            "type": "string",
            "enum": [
              "replace",
              "merge"
            ],
            "default": "replace",
            "description": "Como o `custom_metadata` enviado é reconciliado com o valor armazenado. `replace` (padrão) sobrescreve o objeto inteiro; `merge` faz deep-merge sobre o valor atual — objetos aninhados mesclam recursivamente, escalares e arrays sobrescrevem a chave, e chaves `null` são mantidas (não apagam a chave). Somente em update."
          }
        }
      },
      "EmailBody": {
        "type": "object",
        "required": [
          "text",
          "html"
        ],
        "properties": {
          "text": {
            "type": "string",
            "nullable": true,
            "description": "Corpo em texto simples decodificado da mensagem, ou null quando ausente/não interpretável."
          },
          "html": {
            "type": "string",
            "nullable": true,
            "description": "Corpo HTML decodificado. Não sanitizado — os consumidores devem sanitizar antes de renderizar."
          }
        }
      },
      "Email": {
        "type": "object",
        "required": [
          "id",
          "workspace_id",
          "inbox_id",
          "message_id",
          "from",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "message_id": {
            "type": "string"
          },
          "raw_s3_key": {
            "type": "string"
          },
          "subject": {
            "type": "string",
            "nullable": true
          },
          "from": {
            "type": "string",
            "format": "email"
          },
          "to": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "description": "Destinatários do envelope (RCPT TO) conforme entregue pelo SES. Quando a mensagem foi encaminhada automaticamente, este é o endereço da inbox, não o endereço originalmente digitado pelo remetente."
          },
          "cc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "bcc": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            }
          },
          "header_to": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "email"
            },
            "description": "Valores do header `To:` interpretados literalmente. Difere de `to` quando a mensagem foi encaminhada."
          },
          "forwarded": {
            "type": "boolean",
            "description": "True quando o destinatário do envelope difere do header `To:`, ou quando um header de encaminhamento (Delivered-To, X-Forwarded-To, X-Original-To, Resent-To) está presente."
          },
          "forwarded_for": {
            "type": "string",
            "format": "email",
            "nullable": true,
            "description": "Primeiro endereço do header `To:` que não está no envelope — ou seja, o endereço voltado ao cliente que encaminhou para a inbox."
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "approved",
              "rejected",
              "processing",
              "processed",
              "failed"
            ]
          },
          "rejection_reason": {
            "type": "string",
            "nullable": true
          },
          "spam_verdict": {
            "type": "string",
            "nullable": true
          },
          "virus_verdict": {
            "type": "string",
            "nullable": true
          },
          "aws_ses_metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "agent_metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados de sistema, escritos pela Kobana. Somente leitura."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Graváveis por esta API."
          },
          "sent_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "processed_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "received_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "body": {
            "$ref": "#/components/schemas/EmailBody"
          }
        }
      },
      "UsageDay": {
        "type": "object",
        "required": [
          "date",
          "emails",
          "tokens",
          "cost"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "Dia UTC."
          },
          "emails": {
            "type": "integer",
            "description": "E-mails processados (execuções de agente com sucesso)."
          },
          "tokens": {
            "type": "integer",
            "description": "Tokens de entrada + saída."
          },
          "cost": {
            "type": "number",
            "description": "USD."
          }
        }
      },
      "UsageSummary": {
        "type": "object",
        "description": "Uso do workspace do token em um período, agrupado por dia UTC.",
        "required": [
          "range",
          "totals",
          "series",
          "monthly"
        ],
        "properties": {
          "range": {
            "type": "object",
            "required": [
              "from",
              "to"
            ],
            "properties": {
              "from": {
                "type": "string",
                "format": "date"
              },
              "to": {
                "type": "string",
                "format": "date"
              }
            }
          },
          "totals": {
            "type": "object",
            "required": [
              "emails",
              "tokens",
              "input_tokens",
              "output_tokens",
              "cost"
            ],
            "properties": {
              "emails": {
                "type": "integer"
              },
              "tokens": {
                "type": "integer"
              },
              "input_tokens": {
                "type": "integer"
              },
              "output_tokens": {
                "type": "integer"
              },
              "cost": {
                "type": "number",
                "description": "USD."
              }
            }
          },
          "series": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageDay"
            },
            "description": "Uma entrada por dia do período."
          },
          "monthly": {
            "type": "object",
            "description": "Contadores correntes do mês calendário atual versus os limites do workspace (zerados no dia 1).",
            "required": [
              "emails_used",
              "emails_limit",
              "cost_used",
              "cost_limit"
            ],
            "properties": {
              "emails_used": {
                "type": "integer"
              },
              "emails_limit": {
                "type": "integer",
                "nullable": true
              },
              "cost_used": {
                "type": "number"
              },
              "cost_limit": {
                "type": "number",
                "nullable": true
              }
            }
          }
        }
      },
      "UsageCost": {
        "type": "object",
        "description": "Custo do workspace do token dividido por modelo LLM.",
        "required": [
          "range",
          "totals",
          "models",
          "by_model",
          "series"
        ],
        "properties": {
          "range": {
            "type": "object",
            "required": [
              "from",
              "to"
            ],
            "properties": {
              "from": {
                "type": "string",
                "format": "date"
              },
              "to": {
                "type": "string",
                "format": "date"
              }
            }
          },
          "totals": {
            "type": "object",
            "required": [
              "cost",
              "tokens"
            ],
            "properties": {
              "cost": {
                "type": "number",
                "description": "USD."
              },
              "tokens": {
                "type": "integer"
              }
            }
          },
          "models": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Ids de modelo (`provider/model`) que executaram no período."
          },
          "by_model": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "model",
                "cost",
                "tokens"
              ],
              "properties": {
                "model": {
                  "type": "string"
                },
                "cost": {
                  "type": "number"
                },
                "tokens": {
                  "type": "integer"
                }
              }
            },
            "description": "Totais por modelo, do mais caro para o mais barato."
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "date",
                "by_model"
              ],
              "properties": {
                "date": {
                  "type": "string",
                  "format": "date"
                },
                "by_model": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "number"
                  },
                  "description": "Custo por id de modelo naquele dia (USD)."
                }
              }
            }
          }
        }
      },
      "Model": {
        "type": "object",
        "description": "Um modelo LLM que um agente pode usar: o catálogo do AI Gateway restrito a modelos com preço conhecido.",
        "required": [
          "id",
          "provider",
          "model",
          "name",
          "description",
          "pricing"
        ],
        "properties": {
          "id": {
            "type": "string",
            "example": "anthropic/claude-sonnet-5",
            "description": "Id no gateway, `provider/model`. O valor aceito em `Agent.llm_model`."
          },
          "provider": {
            "type": "string"
          },
          "model": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "pricing": {
            "type": "object",
            "nullable": true,
            "description": "USD por token.",
            "required": [
              "input",
              "output",
              "cache_read",
              "cache_write",
              "valid_from"
            ],
            "properties": {
              "input": {
                "type": "number"
              },
              "output": {
                "type": "number"
              },
              "cache_read": {
                "type": "number"
              },
              "cache_write": {
                "type": "number"
              },
              "valid_from": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Agent": {
        "type": "object",
        "required": [
          "id",
          "external_id",
          "workspace_id",
          "label",
          "llm_model",
          "system_message"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_id": {
            "type": "string",
            "nullable": true
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "label": {
            "type": "string"
          },
          "llm_model": {
            "type": "string"
          },
          "system_message": {
            "type": "string"
          },
          "skills_repo": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "version": {
            "type": "integer",
            "description": "Versão atual do prompt. Incrementada toda vez que `system_message` muda; cada versão é um snapshot imutável listado em `/agents/{id}/versions`."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados de sistema, escritos pela Kobana. Somente leitura."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Graváveis por esta API."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AgentVersion": {
        "type": "object",
        "required": [
          "id",
          "agent_id",
          "version",
          "system_message",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "version": {
            "type": "integer"
          },
          "system_message": {
            "type": "string",
            "description": "Snapshot do prompt desta versão."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AgentCreate": {
        "type": "object",
        "required": [
          "label",
          "llm_model",
          "system_message"
        ],
        "properties": {
          "external_id": {
            "type": "string",
            "minLength": 1,
            "description": "Opcional. Usa por padrão o `id` interno gerado."
          },
          "label": {
            "type": "string",
            "minLength": 1
          },
          "llm_model": {
            "type": "string",
            "minLength": 1
          },
          "system_message": {
            "type": "string",
            "minLength": 1
          },
          "skills_repo": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          }
        }
      },
      "AgentUpdate": {
        "type": "object",
        "required": [],
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1
          },
          "llm_model": {
            "type": "string",
            "minLength": 1
          },
          "system_message": {
            "type": "string"
          },
          "skills_repo": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          },
          "custom_metadata_mode": {
            "type": "string",
            "enum": [
              "replace",
              "merge"
            ],
            "default": "replace",
            "description": "Como o `custom_metadata` enviado é reconciliado com o valor armazenado. `replace` (padrão) sobrescreve o objeto inteiro; `merge` faz deep-merge sobre o valor atual — objetos aninhados mesclam recursivamente, escalares e arrays sobrescrevem a chave, e chaves `null` são mantidas (não apagam a chave). Somente em update."
          }
        }
      },
      "AgentRun": {
        "type": "object",
        "required": [
          "id",
          "workspace_id",
          "inbox_id",
          "agent_id",
          "email_id",
          "llm_model",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": "string",
            "format": "uuid"
          },
          "email_id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_version_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "Snapshot do prompt com o qual a execução rodou (ver `/agents/{id}/versions`). Nulo para execuções registradas antes de existir versionamento."
          },
          "agent_version": {
            "type": "integer",
            "nullable": true,
            "description": "Número da versão do prompt do agente no momento da execução."
          },
          "llm_model": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "running",
              "success",
              "failed"
            ]
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "input_tokens": {
            "type": "integer"
          },
          "output_tokens": {
            "type": "integer"
          },
          "cache_read": {
            "type": "integer"
          },
          "cache_write": {
            "type": "integer"
          },
          "cost_per_token": {
            "type": "number"
          },
          "total_cost": {
            "type": "number"
          },
          "duration_ms": {
            "type": "integer",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "description": "Registro de webhook. Segredos nunca aparecem nas respostas: os signing secrets e os cifrados `auth_basic_password`, `auth_bearer_token` e `auth_header_value`. O `signing_secret` em texto claro é retornado ao lado de `data` exatamente uma vez, na criação e na rotação.",
        "required": [
          "id",
          "external_id",
          "workspace_id",
          "label",
          "url",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "external_id": {
            "type": "string",
            "nullable": true
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "label": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "auth": {
            "type": "string",
            "enum": [
              "none",
              "basic",
              "bearer",
              "header"
            ]
          },
          "auth_basic_user": {
            "type": "string",
            "nullable": true,
            "description": "Somente quando `auth=basic`."
          },
          "auth_header_key": {
            "type": "string",
            "nullable": true,
            "description": "Somente quando `auth=header`."
          },
          "subscribed_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "consecutive_failures": {
            "type": "integer"
          },
          "signing_secret_rotated_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Quando o signing secret foi rotacionado pela última vez; `null` se nunca."
          },
          "signing_secret_previous_expires_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Até quando o signing secret anterior ainda assina entregas após uma rotação; `null` quando não há janela de carência aberta."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados de sistema, escritos pela Kobana. Somente leitura."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Graváveis por esta API."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "label",
          "url"
        ],
        "properties": {
          "external_id": {
            "type": "string",
            "minLength": 1,
            "description": "Opcional. Usa por padrão o `id` interno gerado."
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "subscribed_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "auth": {
            "type": "string",
            "enum": [
              "none",
              "basic",
              "bearer",
              "header"
            ],
            "default": "none"
          },
          "auth_basic_user": {
            "type": "string"
          },
          "auth_basic_password": {
            "type": "string"
          },
          "auth_bearer_token": {
            "type": "string"
          },
          "auth_header_key": {
            "type": "string"
          },
          "auth_header_value": {
            "type": "string"
          },
          "signing_secret": {
            "type": "string",
            "pattern": "^whsec_[A-Za-z0-9+/]+={0,2}$",
            "description": "Opcional. Traga seu próprio signing secret: `whsec_` + base64 padrão de 24-64 bytes aleatórios. Gerado (32 bytes) quando omitido. Retornado em texto claro somente nesta resposta."
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "required": [],
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "subscribed_events": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "inactive"
            ]
          },
          "custom_metadata": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true,
            "description": "Metadados do usuário, formato livre. Envie `null` para limpar. Máx. 64 KB serializados, 16 níveis de profundidade."
          },
          "custom_metadata_mode": {
            "type": "string",
            "enum": [
              "replace",
              "merge"
            ],
            "default": "replace",
            "description": "Como o `custom_metadata` enviado é reconciliado com o valor armazenado. `replace` (padrão) sobrescreve o objeto inteiro; `merge` faz deep-merge sobre o valor atual — objetos aninhados mesclam recursivamente, escalares e arrays sobrescrevem a chave, e chaves `null` são mantidas (não apagam a chave). Somente em update."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": [
          "id",
          "webhook_id",
          "system_event_id",
          "attempt",
          "status"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "system_event_id": {
            "type": "string",
            "format": "uuid"
          },
          "attempt": {
            "type": "integer"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "success",
              "failed"
            ]
          },
          "request_headers": {
            "type": "object",
            "additionalProperties": true
          },
          "request_body": {
            "type": "object",
            "additionalProperties": true
          },
          "response_status": {
            "type": "integer",
            "nullable": true
          },
          "response_headers": {
            "type": "object",
            "additionalProperties": true,
            "nullable": true
          },
          "response_body": {
            "type": "string",
            "nullable": true
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "duration_ms": {
            "type": "integer",
            "nullable": true
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "next_retry_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SystemEvent": {
        "type": "object",
        "required": [
          "id",
          "workspace_id",
          "slug",
          "payload",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "email_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "slug": {
            "type": "string"
          },
          "payload": {
            "type": "object",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WorkspaceUpsert": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WorkspaceCreate"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Casa pelo id interno. Verificado antes de `external_id`."
              },
              "external_id": {
                "type": "string",
                "minLength": 1,
                "description": "Casa pelo id do sistema de origem. Também gravado no registro quando ele é criado."
              }
            }
          }
        ],
        "description": "Corpo do PUT /workspaces: o corpo do POST mais as chaves de busca `id` / `external_id`."
      },
      "InboxUpsert": {
        "allOf": [
          {
            "$ref": "#/components/schemas/InboxCreate"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Casa pelo id interno. Verificado antes de `external_id`."
              },
              "external_id": {
                "type": "string",
                "minLength": 1,
                "description": "Casa pelo id do sistema de origem. Também gravado no registro quando ele é criado."
              }
            }
          }
        ],
        "description": "Corpo do PUT /inboxes: o corpo do POST mais as chaves de busca `id` / `external_id`."
      },
      "AgentUpsert": {
        "allOf": [
          {
            "$ref": "#/components/schemas/AgentCreate"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Casa pelo id interno. Verificado antes de `external_id`."
              },
              "external_id": {
                "type": "string",
                "minLength": 1,
                "description": "Casa pelo id do sistema de origem. Também gravado no registro quando ele é criado."
              }
            }
          }
        ],
        "description": "Corpo do PUT /agents: o corpo do POST mais as chaves de busca `id` / `external_id`."
      },
      "WebhookUpsert": {
        "allOf": [
          {
            "$ref": "#/components/schemas/WebhookCreate"
          },
          {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid",
                "description": "Casa pelo id interno. Verificado antes de `external_id`."
              },
              "external_id": {
                "type": "string",
                "minLength": 1,
                "description": "Casa pelo id do sistema de origem. Também gravado no registro quando ele é criado."
              }
            }
          }
        ],
        "description": "Corpo do PUT /webhooks: o corpo do POST mais as chaves de busca `id` / `external_id`."
      },
      "Secret": {
        "type": "object",
        "description": "Um secret do workspace. O valor é somente escrita: nenhum endpoint, em nenhuma superfície, o devolve.",
        "required": [
          "id",
          "workspace_id",
          "key"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "key": {
            "type": "string",
            "description": "Identificador que um passo de workflow escreve dentro de `${{secrets.KEY}}`. Letras maiúsculas, dígitos e underscores, começando por letra.",
            "example": "FINANCE_TOKEN"
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "last_used_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Última vez que um passo de workflow de fato interpolou este secret."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SecretCreate": {
        "type": "object",
        "required": [
          "key",
          "value"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[A-Z][A-Z0-9_]{0,62}$",
            "example": "FINANCE_TOKEN"
          },
          "value": {
            "type": "string",
            "maxLength": 65536,
            "description": "Guardado criptografado; nunca devolvido."
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "SecretUpsert": {
        "type": "object",
        "required": [
          "key",
          "value"
        ],
        "properties": {
          "key": {
            "type": "string",
            "pattern": "^[A-Z][A-Z0-9_]{0,62}$",
            "description": "Chave de busca do upsert."
          },
          "value": {
            "type": "string",
            "maxLength": 65536
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "SecretUpdate": {
        "type": "object",
        "required": [],
        "properties": {
          "value": {
            "type": "string",
            "maxLength": 65536,
            "description": "Substitui o valor guardado."
          },
          "notes": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "WorkflowRun": {
        "type": "object",
        "required": [
          "id",
          "workspace_id",
          "status",
          "definition",
          "summary"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid"
          },
          "inbox_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "email_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "agent_run_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "success",
              "failed"
            ]
          },
          "definition": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "O array `workflow` exatamente como o agente devolveu, com os placeholders NÃO resolvidos."
          },
          "summary": {
            "type": "object",
            "required": [
              "total",
              "succeeded",
              "error"
            ],
            "properties": {
              "total": {
                "type": "integer"
              },
              "succeeded": {
                "type": "integer"
              },
              "error": {
                "type": "integer",
                "description": "Passos que não tiveram sucesso (`total - succeeded`): os `failed` mais os `skipped` por referenciarem um passo que não teve sucesso. Uma execução pode ter vários de cada."
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true,
            "description": "Preenchido quando a execução falhou: todos os passos que falharam, um por linha, cada um como `step <posição>: <erro>`."
          },
          "duration_ms": {
            "type": "integer",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "steps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkflowStep"
            },
            "description": "Só em `GET /v1/workflow-runs/{id}` — a listagem os omite."
          }
        }
      },
      "WorkflowStep": {
        "type": "object",
        "required": [
          "id",
          "workflow_run_id",
          "position",
          "type",
          "status",
          "request",
          "response"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "workflow_run_id": {
            "type": "string",
            "format": "uuid"
          },
          "position": {
            "type": "integer",
            "description": "Índice base 0 no workflow, que também é a ordem de execução."
          },
          "type": {
            "type": "string",
            "enum": [
              "request"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "running",
              "success",
              "failed",
              "skipped"
            ]
          },
          "request": {
            "type": "object",
            "required": [
              "method",
              "url",
              "headers",
              "body",
              "form"
            ],
            "properties": {
              "method": {
                "type": "string",
                "nullable": true
              },
              "url": {
                "type": "string",
                "nullable": true,
                "description": "URL como enviada, com valores de secrets substituídos por `[REDACTED]`."
              },
              "headers": {
                "type": "object",
                "nullable": true,
                "additionalProperties": {
                  "type": "string"
                }
              },
              "body": {
                "type": "string",
                "nullable": true,
                "description": "Truncado em 4000 caracteres. Um anexo do e-mail referenciado aparece como `[attachment N: nome, content type, tamanho]`, não como os bytes."
              },
              "form": {
                "type": "object",
                "nullable": true,
                "description": "Campos multipart de um passo com `form`, como enviados. Um campo de arquivo é um descritor `{ attachment, filename, content_type, size }` do anexo do e-mail que foi enviado.",
                "additionalProperties": {
                  "oneOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "object",
                      "required": [
                        "attachment",
                        "filename",
                        "content_type",
                        "size"
                      ],
                      "properties": {
                        "attachment": {
                          "type": "integer",
                          "description": "Índice base 0 no e-mail."
                        },
                        "filename": {
                          "type": "string"
                        },
                        "content_type": {
                          "type": "string"
                        },
                        "size": {
                          "type": "integer",
                          "description": "Bytes."
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "response": {
            "type": "object",
            "required": [
              "status",
              "headers",
              "body",
              "expected_status"
            ],
            "properties": {
              "status": {
                "type": "integer",
                "nullable": true
              },
              "headers": {
                "type": "object",
                "nullable": true,
                "additionalProperties": {
                  "type": "string"
                }
              },
              "body": {
                "type": "string",
                "nullable": true,
                "description": "Truncado em 4000 caracteres."
              },
              "expected_status": {
                "type": "integer",
                "nullable": true,
                "description": "Status que conta como sucesso. Null significa qualquer 2xx."
              }
            }
          },
          "error": {
            "type": "string",
            "nullable": true
          },
          "duration_ms": {
            "type": "integer",
            "nullable": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Me": {
        "type": "object",
        "description": "Identidade por trás do token Bearer. Nunca inclui o token nem nada que o identifique.",
        "required": [
          "user",
          "organization",
          "token"
        ],
        "properties": {
          "user": {
            "type": "object",
            "nullable": true,
            "description": "A pessoa por trás do token. `null` quando o token não é de uma pessoa.",
            "required": [
              "id",
              "name",
              "email"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string",
                "nullable": true
              },
              "email": {
                "type": "string",
                "format": "email"
              }
            }
          },
          "organization": {
            "type": "object",
            "required": [
              "id",
              "name",
              "external_id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "name": {
                "type": "string"
              },
              "external_id": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "token": {
            "type": "object",
            "required": [
              "type",
              "scopes",
              "access_level",
              "expires_at"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "oauth",
                  "api_key"
                ],
                "description": "`oauth` para um token emitido por um fluxo de autorização; `api_key` para um criado manualmente no servidor de autorização."
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "access_level": {
                "type": "string",
                "enum": [
                  "read",
                  "write",
                  "all"
                ]
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "JWT RS256 emitido pelo Authorization Server da Kobana (`iss` = `https://account[.<env>].kobana.com.br`), verificado contra as chaves públicas que ele publica — esta API não guarda chave de assinatura e não consegue emitir token. Claims: `iss`, `aud=https://api.inbox[.<env>].kobana.com.br` (pode ser uma lista; a regra é *contém*), `sub`, `jti`, `exp` (obrigatória), `scope` (lista separada por espaços) e `src` opcional (`user`|`system`). Scopes têm dois eixos: um recurso, sempre prefixado pelo app (`inbox/emails`), e um verbo global (`write`). Recurso sem verbo lê; escrita precisa dos dois (`inbox/emails write`). `inbox/all` é o coringa de recurso — lê todos os recursos e não concede verbo. A forma granular `inbox/emails:write` satisfaz os dois eixos para aquele recurso sozinha."
      }
    }
  }
}
