{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "Calebe Pay API",
    "version": "0.4.0",
    "description": "Gateway multi-tenant. API pública /v1 com X-API-Key; painel /admin com Bearer. PIX e boleto têm simulador local sem movimentação financeira. Safe2Pay boleto suporta sandbox; PIX Safe2Pay NÃO possui sandbox. Produção protegida por habilitação explícita. Cobranças em centavos BRL; taxas cadastrais da subconta usam percentual ou reais conforme TaxTypeName. Leia integration.md, boleto.md, subaccounts.md e llms.txt em /docs/. Não há webhook de saída, cartão, split dinâmico por transação ou estorno de escrita nesta versão."
  },
  "servers": [
    {
      "url": "https://api.calebepay.com.br",
      "description": "Origem pública da API configurada para este ambiente."
    }
  ],
  "tags": [
    {
      "name": "API pública"
    },
    {
      "name": "Sessão"
    },
    {
      "name": "Transações do painel"
    },
    {
      "name": "Painel"
    },
    {
      "name": "Subcontas (super admin)"
    },
    {
      "name": "Website (serviço interno)"
    },
    {
      "name": "Cadastros do site (super admin)"
    },
    {
      "name": "Integrações (super admin)"
    },
    {
      "name": "Operação"
    }
  ],
  "paths": {
    "/v1/pix": {
      "post": {
        "operationId": "createPublicPix",
        "tags": [
          "API pública"
        ],
        "summary": "Criar cobrança Pix",
        "description": "Requer pix:write para chave ou papel com escrita para sessão. Nova cobrança exige customer.phone (dígitos, até 20 bytes) e customer.address brasileiro completo, com complemento opcional; falta/invalidez retorna 422 validation_error antes de criar ou chamar o provider. Novas cobranças no simulador seguem o mesmo contrato. Repetição de registro legado com corpo e chave originais permanece válida sem preencher dados ausentes; corpo diferente na mesma chave retorna 409. Nova cobrança 201. Resultado externo incerto 202 com status unknown; não tente nova submissão. Recusa confirmada retorna 502 provider_rejected com error.transaction_id e diagnósticos seguros; isso inclui status failed mesmo com HasError=false remoto. Repetição idempotente retorna 200 com o registro existente, inclusive failed/unknown, sem reenviar ao provedor. GET local recupera o registro sem chamada externa. Simulador gera somente payload de teste. Safe2Pay não oferece Pix sandbox.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Repetição idempotente; mesmo registro.",
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string",
                  "const": "true"
                }
              },
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Processamento em andamento ou resultado externo incerto. Consulte a transação.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{1,128}$"
            },
            "description": "Chave persistida por pedido/tentativa. Mesmo tenant e corpo retornam a mesma transação; corpo diferente gera 409. Não expira automaticamente."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePix"
              }
            }
          }
        }
      }
    },
    "/v1/boleto": {
      "post": {
        "operationId": "createPublicBoleto",
        "tags": [
          "API pública"
        ],
        "summary": "Criar cobrança de boleto",
        "description": "Requer boleto:write explícito para chave, ou papel com escrita para sessão. Provider deve habilitar boleto em enabled_methods e ter regra method=boleto. Vencimento YYYY-MM-DD e endereço brasileiro são obrigatórios. Sem expires_in. Simulador local: simulated=true e URL/linha/código de barras nulos. Safe2Pay sandbox: environment=sandbox e simulated=false; use a credencial sandbox. Produção exige habilitação explícita. Chave idempotente compartilha namespace tenant + key com PIX; reaproveitar chave PIX para boleto retorna 409. Replay conserva o vencimento original e não chama o provider; failed também retorna 200 com o registro existente. Nova recusa confirmada retorna 502 provider_rejected com error.transaction_id e campos provider_error_code/provider_error_message/provider_http_status. Resultado incerto retorna 202 unknown com diagnóstico no DTO. Nunca confirma pagamento pelo HTTP.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Repetição idempotente; mesmo boleto.",
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string",
                  "const": "true"
                }
              },
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Resultado externo incerto; preserve chave e payload.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{1,128}$"
            },
            "description": "Chave persistida por pedido/tentativa. Mesmo tenant e corpo retornam a mesma transação; corpo diferente gera 409. Não expira automaticamente."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBoleto"
              }
            }
          }
        }
      }
    },
    "/v1/transactions": {
      "get": {
        "operationId": "listPublicTransactions",
        "tags": [
          "API pública"
        ],
        "summary": "Listar transações autorizadas",
        "description": "Requer transactions:read para chave. Pública: próprio tenant por padrão, descendentes por opt-in. Admin: árvore do usuário, ou todos para super_admin. count é tamanho da página.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Transaction"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "include_descendants",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Na API pública, inclui descendentes da chave. Na API admin, o escopo padrão já contém descendentes."
          },
          {
            "name": "tenant_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Seleciona raiz do filtro dentro do escopo permitido. Com include_descendants=true, inclui a subárvore selecionada. Não concede novo acesso."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "processing",
                "pending",
                "paid",
                "expired",
                "failed",
                "unknown",
                "refunded"
              ]
            }
          },
          {
            "name": "method",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pix",
                "boleto"
              ]
            }
          },
          {
            "name": "reference",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Correspondência exata da referência comercial; pode retornar mais de uma tentativa."
          }
        ]
      }
    },
    "/v1/transactions/{id}": {
      "get": {
        "operationId": "getPublicTransaction",
        "tags": [
          "API pública"
        ],
        "summary": "Consultar o estado local da transação",
        "description": "Requer transactions:read para chave. Permite própria árvore; fora do escopo retorna 404. Não consulta o provedor. Diagnósticos históricos não capturados permanecem nulos; esta leitura não recupera o erro remoto perdido.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/transactions/{id}/request": {
      "get": {
        "operationId": "getPublicTransactionRequest",
        "tags": [
          "API pública"
        ],
        "summary": "Consultar JSON de criação e corpo preparado para o provider",
        "description": "Leitura local, sem chamada ao provider ou emissão. Requer transactions:read para chave e segue a mesma autorização por hierarquia do GET da transação; fora do escopo retorna 404. Retorna dados pessoais do pagador somente neste detalhe autorizado, nunca adicionados às listagens gerais de Transaction. source=captured identifica corpos persistidos na reserva durável, antes de qualquer envio; request é normalizado e provider_request é preparado, não evidência de transmissão. source=legacy_partial fornece somente dados conhecidos de registros anteriores, com missing_fields explícitos e provider_request null. Não devolve headers, tokens ou Idempotency-Key. Não reconstrua o corpo original nem faça novo POST financeiro a partir de informações parciais.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/TransactionRequest"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/v1/transactions/{id}/refresh": {
      "post": {
        "operationId": "refreshPublicTransaction",
        "tags": [
          "API pública"
        ],
        "summary": "Consultar provedor e atualizar estado local",
        "description": "Requer transactions:read e o scope de escrita do método: pix:write para Pix ou boleto:write para boleto. Viewer não pode atualizar. Em produção, também consulta allow_live_payments efetivo: 403 live_payments_disabled se desativado, 503 payment_settings_unavailable em falha de leitura. GET local continua disponível. Permite transações da árvore autorizada. Sem corpo. Não cria cobrança. Safe2Pay: ID externo, valor e referência interna devem coincidir; divergências preservam o estado local e retornam 502 provider_refresh_failed. Falha no refresh devolve error.transaction_id e diagnósticos da consulta sem sobrescrever o estado ou o diagnóstico de criação persistidos. Resultado unknown sem referência externa pode exigir reconciliação manual. Status processing de boleto ainda não é pagamento confirmado.",
        "security": [
          {
            "TenantAPIKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/pix": {
      "post": {
        "operationId": "createAdminPix",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Criar cobrança Pix",
        "description": "Requer pix:write para chave ou papel com escrita para sessão. Nova cobrança exige customer.phone (dígitos, até 20 bytes) e customer.address brasileiro completo, com complemento opcional; falta/invalidez retorna 422 validation_error antes de criar ou chamar o provider. Novas cobranças no simulador seguem o mesmo contrato. Repetição de registro legado com corpo e chave originais permanece válida sem preencher dados ausentes; corpo diferente na mesma chave retorna 409. Nova cobrança 201. Resultado externo incerto 202 com status unknown; não tente nova submissão. Recusa confirmada retorna 502 provider_rejected com error.transaction_id e diagnósticos seguros; isso inclui status failed mesmo com HasError=false remoto. Repetição idempotente retorna 200 com o registro existente, inclusive failed/unknown, sem reenviar ao provedor. GET local recupera o registro sem chamada externa. Simulador gera somente payload de teste. Safe2Pay não oferece Pix sandbox.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Repetição idempotente; mesmo registro.",
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string",
                  "const": "true"
                }
              },
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Processamento em andamento ou resultado externo incerto. Consulte a transação.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{1,128}$"
            },
            "description": "Chave persistida por pedido/tentativa. Mesmo tenant e corpo retornam a mesma transação; corpo diferente gera 409. Não expira automaticamente."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreatePix"
              }
            }
          }
        }
      }
    },
    "/admin/boleto": {
      "post": {
        "operationId": "createAdminBoleto",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Criar cobrança de boleto",
        "description": "Requer boleto:write explícito para chave, ou papel com escrita para sessão. Provider deve habilitar boleto em enabled_methods e ter regra method=boleto. Vencimento YYYY-MM-DD e endereço brasileiro são obrigatórios. Sem expires_in. Simulador local: simulated=true e URL/linha/código de barras nulos. Safe2Pay sandbox: environment=sandbox e simulated=false; use a credencial sandbox. Produção exige habilitação explícita. Chave idempotente compartilha namespace tenant + key com PIX; reaproveitar chave PIX para boleto retorna 409. Replay conserva o vencimento original e não chama o provider; failed também retorna 200 com o registro existente. Nova recusa confirmada retorna 502 provider_rejected com error.transaction_id e campos provider_error_code/provider_error_message/provider_http_status. Resultado incerto retorna 202 unknown com diagnóstico no DTO. Nunca confirma pagamento pelo HTTP.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Repetição idempotente; mesmo boleto.",
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string",
                  "const": "true"
                }
              },
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Resultado externo incerto; preserve chave e payload.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{1,128}$"
            },
            "description": "Chave persistida por pedido/tentativa. Mesmo tenant e corpo retornam a mesma transação; corpo diferente gera 409. Não expira automaticamente."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateBoleto"
              }
            }
          }
        }
      }
    },
    "/admin/transactions": {
      "get": {
        "operationId": "listAdminTransactions",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Listar transações autorizadas",
        "description": "Requer transactions:read para chave. Pública: próprio tenant por padrão, descendentes por opt-in. Admin: árvore do usuário, ou todos para super_admin. count é tamanho da página.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Transaction"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "include_descendants",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            },
            "description": "Na API pública, inclui descendentes da chave. Na API admin, o escopo padrão já contém descendentes."
          },
          {
            "name": "tenant_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Seleciona raiz do filtro dentro do escopo permitido. Com include_descendants=true, inclui a subárvore selecionada. Não concede novo acesso."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "processing",
                "pending",
                "paid",
                "expired",
                "failed",
                "unknown",
                "refunded"
              ]
            }
          },
          {
            "name": "method",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pix",
                "boleto"
              ]
            }
          },
          {
            "name": "reference",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Correspondência exata da referência comercial; pode retornar mais de uma tentativa."
          }
        ]
      }
    },
    "/admin/transactions/{id}": {
      "get": {
        "operationId": "getAdminTransaction",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Consultar o estado local da transação",
        "description": "Requer transactions:read para chave. Permite própria árvore; fora do escopo retorna 404. Não consulta o provedor. Diagnósticos históricos não capturados permanecem nulos; esta leitura não recupera o erro remoto perdido.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/transactions/{id}/request": {
      "get": {
        "operationId": "getAdminTransactionRequest",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Consultar JSON de criação e corpo preparado para o provider",
        "description": "Leitura local, sem chamada ao provider ou emissão. Requer transactions:read para chave e segue a mesma autorização por hierarquia do GET da transação; fora do escopo retorna 404. Retorna dados pessoais do pagador somente neste detalhe autorizado, nunca adicionados às listagens gerais de Transaction. source=captured identifica corpos persistidos na reserva durável, antes de qualquer envio; request é normalizado e provider_request é preparado, não evidência de transmissão. source=legacy_partial fornece somente dados conhecidos de registros anteriores, com missing_fields explícitos e provider_request null. Não devolve headers, tokens ou Idempotency-Key. Não reconstrua o corpo original nem faça novo POST financeiro a partir de informações parciais.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/TransactionRequest"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/transactions/{id}/refresh": {
      "post": {
        "operationId": "refreshAdminTransaction",
        "tags": [
          "Transações do painel"
        ],
        "summary": "Consultar provedor e atualizar estado local",
        "description": "Requer transactions:read e o scope de escrita do método: pix:write para Pix ou boleto:write para boleto. Viewer não pode atualizar. Em produção, também consulta allow_live_payments efetivo: 403 live_payments_disabled se desativado, 503 payment_settings_unavailable em falha de leitura. GET local continua disponível. Permite transações da árvore autorizada. Sem corpo. Não cria cobrança. Safe2Pay: ID externo, valor e referência interna devem coincidir; divergências preservam o estado local e retornam 502 provider_refresh_failed. Falha no refresh devolve error.transaction_id e diagnósticos da consulta sem sobrescrever o estado ou o diagnóstico de criação persistidos. Resultado unknown sem referência externa pode exigir reconciliação manual. Status processing de boleto ainda não é pagamento confirmado.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/auth/login": {
      "post": {
        "operationId": "login",
        "tags": [
          "Sessão"
        ],
        "summary": "Iniciar sessão do painel",
        "description": "Sessão opaca de 8 horas, armazenada como hash no servidor. Login limitado a 10 tentativas por minuto por IP.",
        "security": [],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Session"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "writeOnly": true
                  }
                },
                "required": [
                  "email",
                  "password"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/auth/me": {
      "get": {
        "operationId": "me",
        "tags": [
          "Sessão"
        ],
        "summary": "Consultar o usuário da sessão",
        "description": "",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/User"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "operationId": "logout",
        "tags": [
          "Sessão"
        ],
        "summary": "Revogar a sessão atual",
        "description": "",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "revoked": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "revoked"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/admin/settings/payments": {
      "get": {
        "operationId": "getPaymentSettings",
        "tags": [
          "Painel"
        ],
        "summary": "Consultar controle global de pagamentos em produção",
        "description": "Somente Bearer de super_admin. Retorna valor efetivo, origem e indicadores dos limites server-side; não expõe o conteúdo do escopo. Leitura dinâmica do banco, sem cache. Criação e refresh remoto em produção usam esse controle; GET local de transações continua disponível. 503 payment_settings_unavailable em falha do banco; não usa fallback de ambiente nesse caso.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PaymentSettings"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "updatePaymentSettings",
        "tags": [
          "Painel"
        ],
        "summary": "Salvar controle global de pagamentos em produção",
        "description": "Somente Bearer de super_admin. Aceita exatamente allow_live_payments boolean obrigatório; campos adicionais ou null são recusados. Salva no banco com auditoria atômica settings.payments.updated (anterior/novo, usuário e request ID) e passa a valer nas próximas verificações, sem reiniciar a API. Não cancela chamada já enviada ao provider. true sozinho não autoriza emissão: ainda exige LIVE_PAYMENT_SCOPE_JSON ou ALLOW_UNSCOPED_LIVE_PAYMENTS=true do servidor. Não altera provider, tenant, credenciais, métodos ou regras. Bootstrap/restart preservam o valor salvo. Nenhuma cobrança é criada por esta operação.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PaymentSettings"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdatePaymentSettings"
              }
            }
          }
        }
      }
    },
    "/admin/subaccounts": {
      "get": {
        "operationId": "listSubaccounts",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Listar vínculos locais de subcontas",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Consulta somente o banco local.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Subaccount"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "tenant_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtro exato, sem incluir descendentes."
          },
          {
            "name": "provider_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Filtro exato, sem incluir descendentes."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "creating",
                "active",
                "unknown",
                "failed"
              ]
            }
          }
        ]
      },
      "post": {
        "operationId": "createSubaccount",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Criar subconta Safe2Pay e vínculo local",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Provider deve ser Safe2Pay com is_marketplace=true e credencial configurada; pode estar desabilitado para pagamentos. Tenant e ancestrais precisam estar ativos. Reserva durável creating antes da chamada externa. Um vínculo não failed por tenant/provider e um vínculo por ID externo/provider. 502 provider_rejected deixa registro failed. Rejeição definitiva sem external_id permite nova tentativa deliberada, cadastro corrigido e nova chave; o registro failed anterior permanece consultável e seu replay não chama Add. Creating/unknown/active bloqueiam outra criação. Recusa Safe2Pay 301 exige corrigir para chave de produção da matriz; mantenha environment=sandbox se a cobrança pretendida for sandbox, sem ativar pagamentos reais.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Repetição idempotente do registro existente, sem chamada remota.",
            "headers": {
              "Idempotency-Replayed": {
                "schema": {
                  "type": "string",
                  "const": "true"
                }
              },
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Resultado externo incerto (unknown) ou replay ainda creating. Consultar e reconciliar sem novo Add.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._:-]{1,128}$"
            },
            "description": "Namespace separado de pagamentos: provider + chave. Persistir antes do envio; repetição com mesmo cadastro não chama Add novamente. Outro cadastro na mesma chave retorna 409."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSubaccount"
              }
            }
          }
        }
      }
    },
    "/admin/subaccounts/{id}": {
      "get": {
        "operationId": "getSubaccount",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Consultar subconta local",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Não consulta o provider.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "operationId": "setSubaccountEnabled",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Habilitar ou desabilitar vínculo local",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Desabilitar não exclui a subconta Safe2Pay. Habilitar exige status active e token do ambiente configurado. Não altera cadastro remoto.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "enabled"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/subaccounts/{id}/credentials": {
      "patch": {
        "operationId": "updateSubaccountCredentials",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Atualizar token armazenado da subconta",
        "description": "Somente sessão Bearer de super_admin. ID local sub_, não ID remoto Safe2Pay. Grava token recuperado ou reemitido fora da Calebe Pay; não solicita novo token nem consulta a Safe2Pay. Atualiza apenas a credencial do ambiente do provider, preservando outro token, signing secrets, tenant, provider, external_id, cadastro e enabled. Não comprova titularidade, validade ou habilitação remota; não emite cobrança nem altera autorizações de produção. 422 validation_error para campos inválidos, ausentes, token mascarado, whitespace/controle ou maior que 8192 bytes. expected_updated_at deve coincidir com a versão atual: 409 subaccount_changed se divergente; 409 subaccount_busy durante operação em curso; 409 reconciliation_required para creating, failed ou sem external_id. unknown só passa a active quando last_error_code é subaccount_credentials_missing; demais unknown mantêm estado e diagnóstico. Retorna DTO sem segredo; auditoria subaccount.credentials_updated não contém token. Não exige Idempotency-Key e não faz retry automático.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSubaccountCredentials"
              }
            }
          }
        }
      }
    },
    "/admin/subaccounts/{id}/registration": {
      "put": {
        "operationId": "updateSubaccountRegistration",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Atualizar cadastro remoto de subconta",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Email e ResponsiblePhone obrigatórios. Não altera Name, Identity ou responsáveis legais. MerchantSplit omitido preserva taxas; presente substitui a configuração integral. Não há retry automático nem criação alternativa. Timeout ou resposta incerta exige refresh/reconciliação antes de nova alteração. Preserva segredos locais utilizáveis, inclusive na confirmação por GET. Valores remotos mascarados não substituem credenciais; apenas valores completos podem preencher lacunas. Não é rotação ou recuperação garantida de token.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Atualização remota com resultado incerto; consultar antes de repetir.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "registration": {
                    "$ref": "#/components/schemas/SubaccountRegistrationUpdate"
                  }
                },
                "required": [
                  "registration"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/subaccounts/{id}/refresh": {
      "post": {
        "operationId": "refreshSubaccount",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Consultar cadastro remoto e sincronizar vínculo",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Sem corpo. Usa GET remoto pelo external_id; nunca Add. Sem external_id: 409 reconciliation_required. Operação em andamento: 409 subaccount_busy. Consulta que concorre com alteração: 409 subaccount_changed, sem sobrescrever o estado mais novo. Identidade e ID devem coincidir. Preserva segredos locais utilizáveis; apenas valores remotos completos e não mascarados podem preencher lacunas. Máscara não substitui nem comprova token. Não recupera de forma garantida credencial perdida; vínculo só fica active com credencial utilizável persistida. Flags has_*_token são recalculados da cifra local e não atestam validade remota.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/subaccounts/link": {
      "post": {
        "operationId": "linkSubaccount",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Importar subconta existente ou reconciliar criação incerta",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Consulta remota confirma ID, documento e tokens informados antes de gravar vínculo. Não cria subconta no provider. Token mascarado no corpo retorna 422 validation_error. Se o provider omitir tokens verificáveis ou devolver máscara, retorna 422 subaccount_credentials_unverifiable, mesmo quando o token original tiver sido informado. Consulta bem-sucedida ou TokenSandbox não comprovam token de produção. Link não recupera token perdido. Prioriza vínculo não failed; se só houver rejeições, recupera o failed mais recente do mesmo tenant/provider, preservando ID e idempotência originais. Sem registro, cria vínculo local com 201; vínculo existente verificado retorna 200. Operação ainda em andamento retorna 409 subaccount_busy. Não exige Idempotency-Key. Nunca envie tokens em query string ou log.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Vínculo existente reconciliado; nenhuma subconta remota criada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subaccount"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkSubaccount"
              }
            }
          }
        }
      }
    },
    "/admin/providers/{id}/subaccounts/remote": {
      "get": {
        "operationId": "listRemoteSubaccounts",
        "tags": [
          "Subcontas (super admin)"
        ],
        "summary": "Consultar subcontas existentes no marketplace",
        "description": "Exige sessão Bearer de super_admin; chaves públicas de tenant não concedem acesso. Nenhum token Safe2Pay é retornado. Gestão exige a chave de produção da MATRIZ, mesmo com provider sandbox; pagamentos continuam usando TokenSandbox da subconta nesse ambiente. Cadastro remoto não é simulação. Erros podem incluir diagnóstico estático e código Safe2Pay numérico em error.message; nunca o texto remoto bruto. Chamada de leitura na Safe2Pay. Projeção sanitizada com ID, nome, documento e e-mail; nunca Integration ou IntegrationData. Não importa nem vincula automaticamente. Paginação remota exige offset múltiplo de limit.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RemoteSubaccount"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 100
                        },
                        "offset": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "count": {
                          "type": "integer",
                          "description": "Quantidade nesta página, não total geral.",
                          "minimum": 0
                        },
                        "total": {
                          "type": "integer",
                          "description": "Total remoto informado pelo provider.",
                          "minimum": 0
                        }
                      },
                      "required": [
                        "limit",
                        "offset",
                        "count",
                        "total"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            },
            "description": "Deve ser múltiplo de limit: com limit=50 use 0, 50, 100 etc. Outras posições retornam 422 validation_error."
          }
        ]
      }
    },
    "/admin/tenants": {
      "get": {
        "operationId": "listTenants",
        "tags": [
          "Painel"
        ],
        "summary": "Listar tenants",
        "description": "Listagem contém a árvore autorizada. Criar/alterar exige super_admin. parent_id e type_id são imutáveis após criação. Suspensão do pai bloqueia o uso por descendentes.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Tenant"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createTenant",
        "tags": [
          "Painel"
        ],
        "summary": "Criar tenants",
        "description": "Listagem contém a árvore autorizada. Criar/alterar exige super_admin. parent_id e type_id são imutáveis após criação. Suspensão do pai bloqueia o uso por descendentes.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tenant"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "slug": {
                    "type": "string",
                    "pattern": "^[a-z0-9][a-z0-9-]{1,62}$"
                  },
                  "type_id": {
                    "type": "string"
                  },
                  "parent_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "document": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "slug",
                  "type_id"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/tenants/{id}": {
      "patch": {
        "operationId": "updateTenant",
        "tags": [
          "Painel"
        ],
        "summary": "Atualizar tenants",
        "description": "Listagem contém a árvore autorizada. Criar/alterar exige super_admin. parent_id e type_id são imutáveis após criação. Suspensão do pai bloqueia o uso por descendentes.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Tenant"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended"
                    ]
                  },
                  "document": {
                    "type": "string"
                  },
                  "email": {
                    "type": "string"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/tenant-types": {
      "get": {
        "operationId": "listTenantTypes",
        "tags": [
          "Painel"
        ],
        "summary": "Listar tenant-types",
        "description": "Leitura por usuários autenticados. Escrita super_admin. Não é possível desabilitar filhos em um tipo já utilizado por tenants pais.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TenantType"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createTenantType",
        "tags": [
          "Painel"
        ],
        "summary": "Criar tenant-types",
        "description": "Leitura por usuários autenticados. Escrita super_admin. Não é possível desabilitar filhos em um tipo já utilizado por tenants pais.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/TenantType"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string"
                  },
                  "can_have_children": {
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/tenant-types/{id}": {
      "patch": {
        "operationId": "updateTenantType",
        "tags": [
          "Painel"
        ],
        "summary": "Atualizar tenant-types",
        "description": "Leitura por usuários autenticados. Escrita super_admin. Não é possível desabilitar filhos em um tipo já utilizado por tenants pais.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/TenantType"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "description": {
                    "type": "string"
                  },
                  "can_have_children": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/users": {
      "get": {
        "operationId": "listUsers",
        "tags": [
          "Painel"
        ],
        "summary": "Listar users",
        "description": "Listagem autorizada pela árvore. Escrita super_admin. tenant_id é obrigatório para tenant_admin/viewer e nulo para super_admin. Papel, tenant e e-mail são imutáveis no PATCH. Alterar senha ou suspender o usuário revoga suas sessões na mesma transação; reativar não recupera sessões antigas.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/User"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createUser",
        "tags": [
          "Painel"
        ],
        "summary": "Criar users",
        "description": "Listagem autorizada pela árvore. Escrita super_admin. tenant_id é obrigatório para tenant_admin/viewer e nulo para super_admin. Papel, tenant e e-mail são imutáveis no PATCH. Alterar senha ou suspender o usuário revoga suas sessões na mesma transação; reativar não recupera sessões antigas.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/User"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "email": {
                    "type": "string"
                  },
                  "password": {
                    "type": "string",
                    "description": "12 a 72 bytes UTF-8.",
                    "writeOnly": true,
                    "minLength": 12,
                    "maxLength": 72
                  },
                  "role": {
                    "type": "string",
                    "enum": [
                      "super_admin",
                      "tenant_admin",
                      "viewer"
                    ]
                  },
                  "tenant_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "required": [
                  "name",
                  "email",
                  "password",
                  "role"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/users/{id}": {
      "patch": {
        "operationId": "updateUser",
        "tags": [
          "Painel"
        ],
        "summary": "Atualizar users",
        "description": "Listagem autorizada pela árvore. Escrita super_admin. tenant_id é obrigatório para tenant_admin/viewer e nulo para super_admin. Papel, tenant e e-mail são imutáveis no PATCH. Alterar senha ou suspender o usuário revoga suas sessões na mesma transação; reativar não recupera sessões antigas.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/User"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "suspended"
                    ]
                  },
                  "password": {
                    "type": "string",
                    "description": "12 a 72 bytes; alterar revoga as sessões do usuário.",
                    "writeOnly": true,
                    "minLength": 12,
                    "maxLength": 72
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/providers": {
      "get": {
        "operationId": "listProviders",
        "tags": [
          "Painel"
        ],
        "summary": "Listar providers",
        "description": "Somente super_admin, inclusive leitura. kind e environment imutáveis. enabled_methods define as capacidades habilitadas; boleto exige opt-in. Simulator somente sandbox; Safe2Pay boleto aceita sandbox e Pix exige production. Em marketplace, api_key guarda a chave de produção da MATRIZ para gestão; a cobrança seleciona TokenSandbox ou Token da subconta conforme environment. Em provider comum, api_key corresponde ao ambiente da cobrança. Produção exige allow_live_payments efetivo habilitado pelo super admin e LIVE_PAYMENT_SCOPE_JSON válido, ou opt-in adicional ALLOW_UNSCOPED_LIVE_PAYMENTS=true. Consulte /admin/settings/payments; ALLOW_LIVE_PAYMENTS no ambiente é apenas padrão inicial/fallback sem registro. Escopo presente sempre restringe. configured não testa a credencial remotamente. is_marketplace só é permitido em Safe2Pay. Com vínculos que não estejam failed, retirar is_marketplace ou trocar api_key retorna 409 marketplace_has_subaccounts. Somente rejeições definitivas failed não bloqueiam essa correção. Marketplace exige vínculo ativo exato do tenant; não herda conta de pai.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Provider"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createProvider",
        "tags": [
          "Painel"
        ],
        "summary": "Criar providers",
        "description": "Somente super_admin, inclusive leitura. kind e environment imutáveis. enabled_methods define as capacidades habilitadas; boleto exige opt-in. Simulator somente sandbox; Safe2Pay boleto aceita sandbox e Pix exige production. Em marketplace, api_key guarda a chave de produção da MATRIZ para gestão; a cobrança seleciona TokenSandbox ou Token da subconta conforme environment. Em provider comum, api_key corresponde ao ambiente da cobrança. Produção exige allow_live_payments efetivo habilitado pelo super admin e LIVE_PAYMENT_SCOPE_JSON válido, ou opt-in adicional ALLOW_UNSCOPED_LIVE_PAYMENTS=true. Consulte /admin/settings/payments; ALLOW_LIVE_PAYMENTS no ambiente é apenas padrão inicial/fallback sem registro. Escopo presente sempre restringe. configured não testa a credencial remotamente. is_marketplace só é permitido em Safe2Pay. Com vínculos que não estejam failed, retirar is_marketplace ou trocar api_key retorna 409 marketplace_has_subaccounts. Somente rejeições definitivas failed não bloqueiam essa correção. Marketplace exige vínculo ativo exato do tenant; não herda conta de pai.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Provider"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "simulator",
                      "safe2pay"
                    ]
                  },
                  "environment": {
                    "type": "string",
                    "enum": [
                      "sandbox",
                      "production"
                    ],
                    "default": "sandbox"
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Obrigatória para Safe2Pay; em marketplace é a chave de PRODUÇÃO da MATRIZ para gestão, mesmo em environment=sandbox. Gravada cifrada e nunca devolvida.",
                    "writeOnly": true
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  },
                  "enabled_methods": {
                    "type": "array",
                    "minItems": 0,
                    "maxItems": 2,
                    "uniqueItems": true,
                    "items": {
                      "type": "string",
                      "enum": [
                        "pix",
                        "boleto"
                      ]
                    },
                    "default": [
                      "pix"
                    ],
                    "description": "Capacidades habilitadas do provider. [] desabilita emissão por todos os métodos. Cadastro existente conserva pix até alteração explícita."
                  },
                  "is_marketplace": {
                    "type": "boolean",
                    "default": false
                  }
                },
                "required": [
                  "name",
                  "kind"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/providers/{id}": {
      "patch": {
        "operationId": "updateProvider",
        "tags": [
          "Painel"
        ],
        "summary": "Atualizar providers",
        "description": "Somente super_admin, inclusive leitura. kind e environment imutáveis. enabled_methods define as capacidades habilitadas; boleto exige opt-in. Simulator somente sandbox; Safe2Pay boleto aceita sandbox e Pix exige production. Em marketplace, api_key guarda a chave de produção da MATRIZ para gestão; a cobrança seleciona TokenSandbox ou Token da subconta conforme environment. Em provider comum, api_key corresponde ao ambiente da cobrança. Produção exige allow_live_payments efetivo habilitado pelo super admin e LIVE_PAYMENT_SCOPE_JSON válido, ou opt-in adicional ALLOW_UNSCOPED_LIVE_PAYMENTS=true. Consulte /admin/settings/payments; ALLOW_LIVE_PAYMENTS no ambiente é apenas padrão inicial/fallback sem registro. Escopo presente sempre restringe. configured não testa a credencial remotamente. is_marketplace só é permitido em Safe2Pay. Com vínculos que não estejam failed, retirar is_marketplace ou trocar api_key retorna 409 marketplace_has_subaccounts. Somente rejeições definitivas failed não bloqueiam essa correção. Marketplace exige vínculo ativo exato do tenant; não herda conta de pai.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Provider"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Substitui a credencial cifrada. Marketplace exige chave de produção da MATRIZ para gestão, independentemente do ambiente das cobranças.",
                    "writeOnly": true
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "enabled_methods": {
                    "type": "array",
                    "minItems": 0,
                    "maxItems": 2,
                    "uniqueItems": true,
                    "items": {
                      "type": "string",
                      "enum": [
                        "pix",
                        "boleto"
                      ]
                    },
                    "default": [
                      "pix"
                    ],
                    "description": "Capacidades habilitadas do provider. [] desabilita emissão por todos os métodos. Cadastro existente conserva pix até alteração explícita."
                  },
                  "is_marketplace": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/rules": {
      "get": {
        "operationId": "listRules",
        "tags": [
          "Painel"
        ],
        "summary": "Listar rules",
        "description": "Somente super_admin, inclusive leitura. Método, tenant e provedor são imutáveis no PATCH. Menor número indica maior prioridade dentro da seleção da rota. O método também deve constar em enabled_methods do provider.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Rule"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createRule",
        "tags": [
          "Painel"
        ],
        "summary": "Criar rules",
        "description": "Somente super_admin, inclusive leitura. Método, tenant e provedor são imutáveis no PATCH. Menor número indica maior prioridade dentro da seleção da rota. O método também deve constar em enabled_methods do provider.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Rule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "tenant_id": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "null = regra global."
                  },
                  "provider_id": {
                    "type": "string"
                  },
                  "method": {
                    "type": "string",
                    "enum": [
                      "pix",
                      "boleto"
                    ],
                    "default": "pix"
                  },
                  "priority": {
                    "type": "integer",
                    "default": 0
                  },
                  "enabled": {
                    "type": "boolean",
                    "default": true
                  },
                  "max_amount": {
                    "type": "integer",
                    "description": "Centavos.",
                    "minimum": 1,
                    "default": 100000000
                  }
                },
                "required": [
                  "name",
                  "provider_id"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/rules/{id}": {
      "patch": {
        "operationId": "updateRule",
        "tags": [
          "Painel"
        ],
        "summary": "Atualizar rules",
        "description": "Somente super_admin, inclusive leitura. Método, tenant e provedor são imutáveis no PATCH. Menor número indica maior prioridade dentro da seleção da rota. O método também deve constar em enabled_methods do provider.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Rule"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "priority": {
                    "type": "integer"
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "max_amount": {
                    "type": "integer",
                    "description": "Centavos.",
                    "minimum": 1
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/summary": {
      "get": {
        "operationId": "getSummary",
        "tags": [
          "Painel"
        ],
        "summary": "Resumo da árvore autorizada",
        "description": "Totais de transações e série usam a mesma janela móvel: created_at >= now() - days. Padrão de 30 dias, permitido de 1 a 365. Contagens de tenants representam o cadastro atual. Todos os valores monetários em centavos. Escopo do usuário e seus descendentes, global para super_admin.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Summary"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "tenant_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 365,
              "default": 30
            },
            "description": "Janela móvel em dias aplicada aos totais de transações e à série."
          }
        ]
      }
    },
    "/admin/api-keys": {
      "get": {
        "operationId": "listAPIKeys",
        "tags": [
          "Painel"
        ],
        "summary": "Listar metadados das chaves",
        "description": "Super_admin ou tenant_admin na própria árvore. Viewer não tem acesso. Não devolve segredos.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/APIKey"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createAPIKey",
        "tags": [
          "Painel"
        ],
        "summary": "Emitir chave de integração",
        "description": "Super_admin ou tenant_admin na própria árvore. Copie data.key nesta resposta; o segredo não pode ser recuperado depois.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/APIKeyCreated"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tenant_id": {
                    "type": "string",
                    "description": "Obrigatório para super_admin; padrão tenant da sessão para tenant_admin."
                  },
                  "name": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "scopes": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 3,
                    "items": {
                      "type": "string",
                      "enum": [
                        "pix:write",
                        "boleto:write",
                        "transactions:read"
                      ]
                    },
                    "default": [
                      "pix:write",
                      "transactions:read"
                    ],
                    "description": "boleto:write exige opt-in explícito; não é concedido a chaves antigas nem no padrão de criação."
                  }
                },
                "required": [
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/api-keys/{id}": {
      "delete": {
        "operationId": "revokeAPIKey",
        "tags": [
          "Painel"
        ],
        "summary": "Revogar chave de integração",
        "description": "Super_admin ou tenant_admin na própria árvore. Revogação persiste para chamadas posteriores.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "revoked": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "revoked"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/transactions/{id}/simulate": {
      "post": {
        "operationId": "simulateTransaction",
        "tags": [
          "Painel"
        ],
        "summary": "Mudar estado de uma transação simulada",
        "description": "Somente transação do simulador e usuário com escrita no escopo autorizado. Nunca move dinheiro ou confirma cobrança Safe2Pay.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Transaction"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "paid",
                      "expired"
                    ]
                  }
                },
                "required": [
                  "status"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/audit-logs": {
      "get": {
        "operationId": "listAuditLogs",
        "tags": [
          "Painel"
        ],
        "summary": "Consultar trilha administrativa autorizada",
        "description": "",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AuditLog"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      }
    },
    "/admin/notifications": {
      "get": {
        "operationId": "listNotifications",
        "tags": [
          "Painel"
        ],
        "summary": "Listar notificações da árvore autorizada",
        "description": "Notificação interna do portal. Não envia e-mail, SMS, push ou webhook. Notificações com tenant_id nulo ficam no super_admin.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Notification"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createNotification",
        "tags": [
          "Painel"
        ],
        "summary": "Criar notificação interna",
        "description": "Somente super_admin.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Notification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "tenant_id": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "title": {
                    "type": "string",
                    "description": "Nome; validação do servidor: 2 a 120 bytes após as regras do endpoint.",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "message": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 2000
                  },
                  "severity": {
                    "type": "string",
                    "enum": [
                      "info",
                      "warning",
                      "error",
                      "success"
                    ],
                    "default": "info"
                  }
                },
                "required": [
                  "title",
                  "message"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/notifications/{id}": {
      "patch": {
        "operationId": "markNotificationRead",
        "tags": [
          "Painel"
        ],
        "summary": "Marcar notificação como lida/não lida",
        "description": "Qualquer usuário com acesso à notificação. Estado de leitura é do registro compartilhado, não individual por usuário. Omissão de read equivale a false.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Notification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "read": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "operationId": "health",
        "tags": [
          "Operação"
        ],
        "summary": "Liveness da API",
        "description": "",
        "security": [],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "const": "ok"
                        },
                        "service": {
                          "type": "string",
                          "const": "calebe-pay-api"
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/ready": {
      "get": {
        "operationId": "ready",
        "tags": [
          "Operação"
        ],
        "summary": "Readiness de PostgreSQL e Redis",
        "description": "",
        "security": [],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "status": {
                          "type": "string",
                          "const": "ready"
                        }
                      },
                      "required": [
                        "status"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "operationId": "metrics",
        "tags": [
          "Operação"
        ],
        "summary": "Contadores Prometheus",
        "security": [],
        "description": "Restrinja o acesso na borda da rede em produção. Métricas iniciais de contagem de requests e erros.",
        "responses": {
          "200": {
            "description": "Texto Prometheus.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/website/onboarding": {
      "post": {
        "operationId": "submitWebsiteApplication",
        "tags": [
          "Website (serviço interno)"
        ],
        "summary": "Receber solicitação de cadastro do website",
        "description": "Somente servidor do website com X-Website-Key dedicado (WEBSITE_API_KEY). Não use chave de tenant, sessão de usuário ou token Safe2Pay. Não exponha a chave no navegador. O website acessa via proxy same-origin /api/. Erros usam o envelope padrão Go; o proxy converte error.message em error string para o formulário. JSON até 64 KiB, valida CPF/CNPJ, campos obrigatórios e consentimentos. Persiste no PostgreSQL e devolve referência + credencial temporária de upload (somente hash armazenado). Honeypot preenchido retorna apenas {ok:true}. Não cria tenant, usuário, subconta ou cobrança. Sem retry automático; duplo envio pode gerar solicitações distintas.",
        "security": [
          {
            "WebsiteServiceKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebsiteApplicationCreated"
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebsiteApplicationInput"
              }
            }
          }
        }
      }
    },
    "/website/onboarding/documents": {
      "post": {
        "operationId": "uploadWebsiteDocument",
        "tags": [
          "Website (serviço interno)"
        ],
        "summary": "Receber documento cadastral privado",
        "description": "Somente servidor do website com X-Website-Key dedicado (WEBSITE_API_KEY). Não use chave de tenant, sessão de usuário ou token Safe2Pay. Não exponha a chave no navegador. O website acessa via proxy same-origin /api/. Erros usam o envelope padrão Go; o proxy converte error.message em error string para o formulário. Multipart até 11 MiB, arquivo até 10 MiB. Valida credencial temporária e assinatura real de PDF/JPEG/PNG. No máximo um arquivo por categoria: novo envio válido substitui o anterior atomicamente. Metadados ficam no PostgreSQL, bytes em MinIO/S3 privado no storage padrão ativo. Cada documento preserva a conexão original; mudar o padrão afeta apenas novos uploads. Upload e download verificam tamanho e SHA-256. Sem URL pública. 503 storage_not_configured quando não houver padrão ativo. Credencial inválida/expirada retorna 403.",
        "security": [
          {
            "WebsiteServiceKey": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "const": true
                    },
                    "documentType": {
                      "type": "string",
                      "enum": [
                        "company",
                        "representative",
                        "address",
                        "bank",
                        "ownership"
                      ]
                    }
                  },
                  "required": [
                    "ok",
                    "documentType"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "reference": {
                    "type": "string"
                  },
                  "uploadToken": {
                    "type": "string",
                    "description": "Credencial de upload da solicitação.",
                    "writeOnly": true
                  },
                  "documentType": {
                    "type": "string",
                    "enum": [
                      "company",
                      "representative",
                      "address",
                      "bank",
                      "ownership"
                    ]
                  },
                  "file": {
                    "type": "string",
                    "format": "binary"
                  }
                },
                "required": [
                  "reference",
                  "uploadToken",
                  "documentType",
                  "file"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/website/lookups": {
      "get": {
        "operationId": "lookupWebsiteRegistration",
        "tags": [
          "Website (serviço interno)"
        ],
        "summary": "Consultar CNPJ, CEP ou instituições financeiras",
        "description": "Somente servidor do website com X-Website-Key dedicado (WEBSITE_API_KEY). Não use chave de tenant, sessão de usuário ou token Safe2Pay. Não exponha a chave no navegador. O website acessa via proxy same-origin /api/. Erros usam o envelope padrão Go; o proxy converte error.message em error string para o formulário. Consulta BrasilAPI a partir da API Go. Falha não impede preenchimento manual; 404 para registro ausente e 503 para indisponibilidade externa. Não equivale a aprovação cadastral.",
        "security": [
          {
            "WebsiteServiceKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      },
                      "description": "Campos camelCase da empresa/endereço, preenchimento auxiliar."
                    },
                    {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "code": {
                            "type": [
                              "integer",
                              "null"
                            ]
                          },
                          "name": {
                            "type": "string"
                          },
                          "ispb": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "cnpj",
                "cep",
                "banks"
              ]
            }
          },
          {
            "name": "value",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "CNPJ numérico ou CEP, conforme kind; omitido para banks."
            }
          }
        ]
      }
    },
    "/admin/website-applications": {
      "get": {
        "operationId": "listWebsiteApplications",
        "tags": [
          "Cadastros do site (super admin)"
        ],
        "summary": "Listar cadastros recebidos no website",
        "description": "Somente sessão Bearer de super_admin. Tenant_admin, viewer e chaves de tenant não podem consultar cadastros ou documentos. Leituras cadastrais locais, sem chamadas financeiras; download acessa armazenamento privado. Paginação limit/offset; meta.count é a quantidade retornada na página. Não inclui payload completo, credenciais ou bytes dos documentos.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebsiteApplicationSummary"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string",
              "description": "Busca por referência, empresa, CNPJ ou e-mail."
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "received",
                "in_review",
                "archived"
              ]
            }
          }
        ]
      }
    },
    "/admin/website-applications/{id}": {
      "get": {
        "operationId": "getWebsiteApplication",
        "tags": [
          "Cadastros do site (super admin)"
        ],
        "summary": "Consultar cadastro e metadados dos documentos",
        "description": "Somente sessão Bearer de super_admin. Tenant_admin, viewer e chaves de tenant não podem consultar cadastros ou documentos. Leituras cadastrais locais, sem chamadas financeiras; download acessa armazenamento privado. Dados pessoais e bancários restritos a esta consulta. conversion_status deriva da subconta atual, refletindo reconciliação posterior; unknown exige consulta/reconciliação antes de novo cadastro remoto. Nunca retorna token/hash de upload nem bytes dos arquivos.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebsiteApplicationDetail"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "operationId": "reviewWebsiteApplication",
        "tags": [
          "Cadastros do site (super admin)"
        ],
        "summary": "Atualizar acompanhamento interno do cadastro",
        "description": "Somente sessão Bearer de super_admin. Tenant_admin, viewer e chaves de tenant não podem consultar cadastros ou documentos. Leituras cadastrais locais, sem chamadas financeiras; download acessa armazenamento privado. received=recebido, in_review=em análise, archived=arquivado. Registra auditoria. Alterar o acompanhamento não aprova KYC, não cria tenant/usuário nem habilita provider.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebsiteApplicationDetail"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "received",
                      "in_review",
                      "archived"
                    ]
                  },
                  "review_notes": {
                    "type": "string",
                    "description": "Até 4.000 bytes."
                  }
                },
                "required": [
                  "status",
                  "review_notes"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/website-applications/{id}/documents/{documentID}": {
      "get": {
        "operationId": "downloadWebsiteDocument",
        "tags": [
          "Cadastros do site (super admin)"
        ],
        "summary": "Baixar documento privado do cadastro",
        "description": "Somente sessão Bearer de super_admin. Tenant_admin, viewer e chaves de tenant não podem consultar cadastros ou documentos. Leituras cadastrais locais, sem chamadas financeiras; download acessa armazenamento privado. Documento deve pertencer à solicitação. Download autenticado auditado com Content-Disposition: attachment, Cache-Control: no-store e X-Content-Type-Options: nosniff.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Conteúdo original do documento, nunca JSON/base64.",
            "headers": {
              "Content-Disposition": {
                "schema": {
                  "type": "string"
                }
              },
              "Cache-Control": {
                "schema": {
                  "type": "string",
                  "const": "no-store"
                }
              }
            },
            "content": {
              "application/pdf": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/jpeg": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              },
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "documentID",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ]
      }
    },
    "/admin/website-applications/{id}/convert": {
      "post": {
        "operationId": "convertWebsiteApplication",
        "tags": [
          "Cadastros do site (super admin)"
        ],
        "summary": "Converter cadastro em tenant e subconta Safe2Pay",
        "description": "Somente sessão Bearer de super_admin. Tenant_admin, viewer e chaves de tenant não podem consultar cadastros ou documentos. Leituras cadastrais locais, sem chamadas financeiras; download acessa armazenamento privado. Ação explícita que cria subconta REAL na Safe2Pay, inclusive quando provider está marcado sandbox. Revisa cadastro preenchido pelo site e exige dados completos da subconta. Reserva tenant + subconta + histórico atomicamente antes do Add remoto. Tipo e hierarquia validados. Não cria usuário, chave de API, regra de roteamento ou cobrança. Repetição da mesma chave/corpo devolve tentativa existente; corpo diferente retorna409. unknown/creating bloqueiam nova criação: consulte vínculo e reconcilie em Subcontas. Recusa definitiva failed sem external_id permite corrigir registration e usar nova chave; reutiliza tenant original, com tenant/provider imutáveis. Interprete data.conversion_status mesmo no HTTP200: failed contém diagnóstico seguro e não representa cadastro aprovado.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Replay ou recusa definitiva preservada; avaliar estado/erro no corpo.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebsiteConversionResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebsiteConversionResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Em curso ou resultado externo incerto; não iniciar outra criação.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WebsiteConversionResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Objeto inválido, campos duplicados/desconhecidos, cadastro incompleto ou documento inválido.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial de serviço ou sessão ausente/inválida.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel/origem não autorizado ou credencial de upload inválida/expirada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Cadastro, documento ou registro auxiliar não encontrado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de integridade no armazenamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Limite excedido: JSON 64 KiB, multipart 11 MiB e arquivo 10 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Status, busca ou observações inválidos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido; aguarde 60 segundos.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Falha interna ao concluir a operação.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Configuração de serviço, controle de acesso ou consulta auxiliar indisponível.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            },
            "description": "Persistir chave e corpo antes de enviar. Namespace do cadastro; replay nunca chama Add novamente."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebsiteConversionInput"
              }
            }
          }
        }
      }
    },
    "/admin/integrations/catalog": {
      "get": {
        "operationId": "getIntegrationCatalog",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Obter catálogo de canais, adapters e campos",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. A interface deve usar secret/type/required para renderizar o formulário. Providers adicionais exigem implementação de adapter no servidor; várias conexões do mesmo provider são permitidas.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IntegrationCatalogEntry"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/admin/integrations": {
      "get": {
        "operationId": "listIntegrations",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Listar conexões de e-mail, WhatsApp e armazenamento",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. ",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/IntegrationConnection"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 100
            },
            "description": "Valores acima de 100 são limitados a 100."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "default": 0
            }
          }
        ]
      },
      "post": {
        "operationId": "createIntegration",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Cadastrar conexão",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. enabled e is_default iniciam false. JSON até 64 KiB. Campos obrigatórios do catálogo são exigidos ao habilitar. Seleção do padrão e auditoria são atômicas.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "201": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IntegrationConnection"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "channel": {
                    "type": "string",
                    "enum": [
                      "email",
                      "whatsapp",
                      "storage"
                    ]
                  },
                  "provider": {
                    "type": "string",
                    "enum": [
                      "smtp",
                      "resend",
                      "evolution",
                      "meta",
                      "twilio",
                      "minio",
                      "s3"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 140
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "is_default": {
                    "type": "boolean",
                    "description": "Máximo de um padrão ativo por canal. Definir outro retira o anterior atomicamente. Desabilitar retira padrão. Configurar padrão não envia mensagens."
                  },
                  "config": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    },
                    "description": "Somente campos não secretos do catálogo. SMTP: host,port,security(starttls|tls|none),from_email,from_name. Resend: from_email,from_name. Evolution: base_url,instance. Meta: phone_number_id,api_version. Twilio: account_sid,from_number. MinIO/S3: endpoint,bucket,region,use_ssl,force_path_style. Endpoint S3 deve ser origem HTTP(S) sem caminho/query; use_ssl corresponde ao protocolo. Bucket privado previamente existente. Consulte integrations.md."
                  },
                  "credentials": {
                    "type": "object",
                    "writeOnly": true,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 8192
                    },
                    "description": "SMTP: username,password (par opcional). Resend/Evolution: api_key. Meta: access_token. Twilio: auth_token. MinIO/S3: access_key,secret_key,session_token(opcional). PATCH omissão preserva; valor vazio remove credencial opcional. Campos obrigatórios impedem habilitação sem segredo. Nunca enviar em URL ou registrar em logs; nunca retornados."
                  }
                },
                "required": [
                  "channel",
                  "provider",
                  "name"
                ],
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/integrations/{id}": {
      "get": {
        "operationId": "getIntegration",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Consultar conexão sem revelar segredos",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. ",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IntegrationConnection"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ]
      },
      "patch": {
        "operationId": "updateIntegration",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Editar conexão ou substituir credenciais",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. PATCH parcial; config e credentials são mesclados por campo. Canal/provider imutáveis. Com anexos vinculados, endpoint/bucket/região/HTTPS/modo de acesso não podem mudar (409 storage_has_documents); crie outra conexão e defina como padrão. Downloads anteriores continuam usando a conexão original, mesmo desabilitada para novos uploads. Rotação de credenciais exige acesso aos mesmos objetos.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/IntegrationConnection"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 140
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "is_default": {
                    "type": "boolean",
                    "description": "Máximo de um padrão ativo por canal. Definir outro retira o anterior atomicamente. Desabilitar retira padrão. Configurar padrão não envia mensagens."
                  },
                  "config": {
                    "type": "object",
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    },
                    "description": "Somente campos não secretos do catálogo. SMTP: host,port,security(starttls|tls|none),from_email,from_name. Resend: from_email,from_name. Evolution: base_url,instance. Meta: phone_number_id,api_version. Twilio: account_sid,from_number. MinIO/S3: endpoint,bucket,region,use_ssl,force_path_style. Endpoint S3 deve ser origem HTTP(S) sem caminho/query; use_ssl corresponde ao protocolo. Bucket privado previamente existente. Consulte integrations.md."
                  },
                  "credentials": {
                    "type": "object",
                    "writeOnly": true,
                    "additionalProperties": {
                      "type": "string",
                      "maxLength": 8192
                    },
                    "description": "SMTP: username,password (par opcional). Resend/Evolution: api_key. Meta: access_token. Twilio: auth_token. MinIO/S3: access_key,secret_key,session_token(opcional). PATCH omissão preserva; valor vazio remove credencial opcional. Campos obrigatórios impedem habilitação sem segredo. Nunca enviar em URL ou registrar em logs; nunca retornados."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    },
    "/admin/integrations/{id}/test": {
      "post": {
        "operationId": "testIntegration",
        "tags": [
          "Integrações (super admin)"
        ],
        "summary": "Testar acesso ao bucket ou enviar mensagem explícita",
        "description": "Somente sessão Bearer de super_admin; chaves de tenant não autorizam. Credenciais cifradas no PostgreSQL com ENCRYPTION_KEY. Configurar não faz envio nem modifica providers financeiros. Conexão habilitada; máximo de 5 testes/minuto por administrador. Storage aceita {} e apenas consulta existência/acesso ao bucket. E-mail/WhatsApp envia de fato ao destinatário informado, somente nesta ação; não há envio automático por evento. WhatsApp texto livre depende da janela de atendimento do provider; templates ainda não implementados. Sem retry automático. 502 notification_not_confirmed pode representar envio já recebido: consultar provider antes de repetir. SMTP possui TLS/starttls/none; HTTP remoto limita tempo e resposta e bloqueia redirects.",
        "security": [
          {
            "SessionBearer": []
          }
        ],
        "responses": {
          "200": {
            "description": "Sucesso.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "success": {
                          "type": "boolean",
                          "const": true
                        },
                        "message": {
                          "type": "string"
                        },
                        "provider_message_id": {
                          "type": "string",
                          "description": "Quando disponível, ID de aceite no provider; não comprova entrega."
                        }
                      },
                      "required": [
                        "success",
                        "message"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "JSON inválido, nulo, campos duplicados/desconhecidos ou Idempotency-Key ausente/inválida.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Credencial ausente, inválida, revogada ou expirada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Papel, scope, origem, tenant ou escopo de pagamento real não autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Recurso ausente ou fora do escopo autorizado.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflito de dados ou idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "Corpo JSON excede o limite de 1 MiB. Código request_too_large.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "Validação ou configuração de provedor não suportada.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Limite de chamadas excedido. Aguarde pelo menos 60 segundos.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Erro interno.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "Falha/rejeição do provedor; preserve a idempotência.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "Dependência, rota ou controle de acesso indisponível.",
            "headers": {
              "X-Request-ID": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Identificador opaco retornado pela API.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "recipient": {
                    "type": "string",
                    "description": "E-mail válido ou WhatsApp E.164 (+5511...). Obrigatório para notificações."
                  },
                  "message": {
                    "type": "string",
                    "description": "Mensagem explícita de teste; obrigatória para notificações.",
                    "maxLength": 1600
                  }
                },
                "additionalProperties": false
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "WebsiteServiceKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Website-Key",
        "description": "Chave exclusiva do servidor do website; não expor no navegador. Não autoriza pagamentos nem operações de tenant."
      },
      "TenantAPIKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Chave do tenant. Usar somente no servidor integrador."
      },
      "SessionBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "opaque session",
        "description": "Token retornado por /auth/login; validade 8 horas."
      }
    },
    "schemas": {
      "PaymentSettings": {
        "type": "object",
        "properties": {
          "allow_live_payments": {
            "type": "boolean",
            "description": "Valor efetivo persistido pelo super admin. Sem registro, usa o padrão de ambiente."
          },
          "source": {
            "type": "string",
            "enum": [
              "database",
              "environment"
            ],
            "description": "Origem do valor efetivo; environment só ocorre quando o registro não existe, nunca em falha de banco."
          },
          "environment_default": {
            "type": "boolean",
            "description": "Valor de ALLOW_LIVE_PAYMENTS carregado do ambiente para bootstrap/fallback; não sobrescreve configuração já salva."
          },
          "allow_unscoped_live_payments": {
            "type": "boolean",
            "description": "Flag ALLOW_UNSCOPED_LIVE_PAYMENTS do servidor; somente leitura nesta API."
          },
          "has_live_payment_scope": {
            "type": "boolean",
            "description": "Indica existência de LIVE_PAYMENT_SCOPE_JSON; os detalhes do escopo não são expostos."
          },
          "issuance_authorized": {
            "type": "boolean",
            "description": "allow_live_payments e autorização por escopo ou flag sem escopo. Não comprova configuração de provider, rota, subconta ou credenciais válidas."
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_by": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID do último usuário administrador que salvou; pode ser nulo no bootstrap/fallback."
          }
        },
        "required": [
          "allow_live_payments",
          "source",
          "environment_default",
          "allow_unscoped_live_payments",
          "has_live_payment_scope",
          "issuance_authorized",
          "updated_at",
          "updated_by"
        ],
        "examples": [
          {
            "allow_live_payments": false,
            "source": "database",
            "environment_default": false,
            "allow_unscoped_live_payments": false,
            "has_live_payment_scope": false,
            "issuance_authorized": false,
            "updated_at": "2026-09-18T12:00:00Z",
            "updated_by": null
          }
        ]
      },
      "UpdatePaymentSettings": {
        "type": "object",
        "properties": {
          "allow_live_payments": {
            "type": "boolean",
            "description": "Único campo editável. Não amplia os limites de autorização do servidor."
          }
        },
        "required": [
          "allow_live_payments"
        ],
        "additionalProperties": false
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Código estável para decisões do integrador."
              },
              "message": {
                "type": "string",
                "description": "Mensagem legível; diagnóstico de pagamentos usa texto seguro, nunca o retorno bruto do provider."
              },
              "request_id": {
                "type": "string",
                "description": "ID desta requisição para correlação com o log/auditoria; não é um campo da transação."
              },
              "transaction_id": {
                "type": "string",
                "description": "Opcional: ID da transação local, quando a operação chegou à reserva persistente. Consulte GET /v1/transactions/{id}; não reenvie para obter detalhes."
              },
              "provider_error_code": {
                "type": [
                  "string",
                  "null"
                ],
                "pattern": "^[0-9]{1,10}$",
                "description": "Código numérico do provider, sanitizado. Nulo quando ausente, inválido ou não capturado no histórico; não inferir motivo a partir de null."
              },
              "provider_error_message": {
                "type": [
                  "string",
                  "null"
                ],
                "maxLength": 400,
                "description": "Orientação estática segura da Calebe Pay, sem Error/Message bruto, tokens ou dados pessoais do provider."
              },
              "provider_http_status": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 100,
                "maximum": 599,
                "description": "Status HTTP observado na resposta do provider, diferente do HTTP da Calebe Pay. Pode ser 200 numa recusa de negócio. Nulo se não houve resposta ou não foi capturado."
              }
            },
            "required": [
              "code",
              "message",
              "request_id"
            ]
          }
        },
        "required": [
          "error"
        ],
        "examples": [
          {
            "error": {
              "code": "idempotency_conflict",
              "message": "A chave de idempotência já foi usada com outro corpo.",
              "request_id": "req_exemplo"
            }
          },
          {
            "error": {
              "code": "provider_rejected",
              "message": "O provider recusou a cobrança. Confira a configuração.",
              "request_id": "req_recusa_exemplo",
              "transaction_id": "txn_recusa_exemplo",
              "provider_error_code": null,
              "provider_error_message": "O provider recusou a cobrança. Confira a configuração.",
              "provider_http_status": 200
            }
          }
        ]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          },
          "count": {
            "type": "integer",
            "description": "Quantidade nesta página, não total geral.",
            "minimum": 0
          }
        },
        "required": [
          "limit",
          "offset",
          "count"
        ]
      },
      "CustomerAddress": {
        "type": "object",
        "properties": {
          "zip_code": {
            "type": "string",
            "description": "CEP sem pontuação.",
            "pattern": "^[0-9]{8}$"
          },
          "street": {
            "type": "string",
            "description": "Logradouro; 2 a 120 bytes.",
            "minLength": 2,
            "maxLength": 120
          },
          "number": {
            "type": "string",
            "description": "Número como string; aceita S/N.",
            "minLength": 1,
            "maxLength": 20
          },
          "complement": {
            "type": "string",
            "description": "Complemento; máximo 120 bytes.",
            "maxLength": 120
          },
          "district": {
            "type": "string",
            "description": "Bairro; 2 a 80 bytes.",
            "minLength": 2,
            "maxLength": 80
          },
          "city": {
            "type": "string",
            "description": "Cidade; 2 a 80 bytes.",
            "minLength": 2,
            "maxLength": 80
          },
          "state": {
            "type": "string",
            "enum": [
              "AC",
              "AL",
              "AP",
              "AM",
              "BA",
              "CE",
              "DF",
              "ES",
              "GO",
              "MA",
              "MT",
              "MS",
              "MG",
              "PA",
              "PB",
              "PR",
              "PE",
              "PI",
              "RJ",
              "RN",
              "RS",
              "RO",
              "RR",
              "SC",
              "SP",
              "SE",
              "TO"
            ]
          }
        },
        "required": [
          "zip_code",
          "street",
          "number",
          "district",
          "city",
          "state"
        ],
        "additionalProperties": false
      },
      "Customer": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nome do pagador; 2 a 120 bytes UTF-8.",
            "minLength": 2,
            "maxLength": 120
          },
          "document": {
            "type": "string",
            "description": "CPF/CNPJ como string; 11 ou 14 caracteres alfanuméricos sem pontuação. Validação de formato, sem conferência de dígitos verificadores.",
            "pattern": "^([A-Za-z0-9]{11}|[A-Za-z0-9]{14})$"
          },
          "email": {
            "type": "string",
            "description": "E-mail do pagador; deve conter @; máximo 254 bytes.",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "description": "Telefone opcional como string; máximo 20 bytes.",
            "maxLength": 20
          },
          "address": {
            "$ref": "#/components/schemas/CustomerAddress"
          }
        },
        "required": [
          "name",
          "document",
          "email"
        ],
        "additionalProperties": false
      },
      "BoletoOptions": {
        "type": "object",
        "properties": {
          "due_date": {
            "type": "string",
            "description": "Data em YYYY-MM-DD. Nova emissão aceita hoje até 365 dias à frente em America/Sao_Paulo. Replay idempotente conserva a data original, mesmo vencida.",
            "format": "date",
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}$"
          },
          "instruction": {
            "type": "string",
            "description": "Instrução impressa; máximo 200 bytes.",
            "maxLength": 200
          },
          "penalty_rate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "multipleOf": 0.01,
            "default": 0,
            "description": "Percentual de multa, no máximo duas casas decimais."
          },
          "interest_rate": {
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "multipleOf": 0.01,
            "default": 0,
            "description": "Percentual de juros enviado ao provider, no máximo duas casas decimais."
          },
          "cancel_after_due": {
            "type": "boolean",
            "default": false
          },
          "days_before_cancel": {
            "type": "integer",
            "description": "Dias para baixa após vencimento, conforme a configuração do provider.",
            "minimum": 0,
            "maximum": 120,
            "default": 0
          }
        },
        "required": [
          "due_date"
        ],
        "additionalProperties": false
      },
      "CreatePix": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "description": "Centavos BRL. 1250 = R$ 12,50.",
            "minimum": 1,
            "maximum": 100000000
          },
          "reference": {
            "type": "string",
            "description": "Correlação com o pedido, não exclusiva.",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "description": "Descrição da cobrança.",
            "minLength": 1,
            "maxLength": 200
          },
          "customer": {
            "$ref": "#/components/schemas/PixCustomer"
          },
          "expires_in": {
            "type": "integer",
            "description": "Expiração em segundos.",
            "minimum": 60,
            "maximum": 86400,
            "default": 3600
          }
        },
        "required": [
          "amount",
          "reference",
          "description",
          "customer"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "amount": 1250,
            "reference": "pedido-2026-00042",
            "description": "Pedido de demonstração",
            "customer": {
              "name": "Cliente de demonstração",
              "document": "00000000000",
              "email": "cliente@example.com",
              "phone": "11999999999",
              "address": {
                "zip_code": "01001000",
                "street": "Rua Exemplo",
                "number": "100",
                "district": "Centro",
                "city": "São Paulo",
                "state": "SP"
              }
            },
            "expires_in": 3600
          }
        ]
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID local opaco."
          },
          "tenant_id": {
            "type": "string"
          },
          "tenant_name": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "provider_name": {
            "type": "string"
          },
          "provider_reference": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "Vínculo local exato tenant/provider usado na emissão. Nulo para provider comum. Consultas ao provider reutilizam este vínculo original."
          },
          "amount": {
            "type": "integer",
            "description": "Centavos BRL."
          },
          "currency": {
            "const": "BRL",
            "type": "string"
          },
          "method": {
            "type": "string",
            "enum": [
              "pix",
              "boleto"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "pending",
              "paid",
              "expired",
              "failed",
              "unknown",
              "refunded"
            ]
          },
          "reference": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ]
          },
          "simulated": {
            "type": "boolean",
            "description": "true significa simulação local, sem pagamento possível."
          },
          "pix_copy_paste": {
            "type": [
              "string",
              "null"
            ],
            "description": "Payload Pix real ou marcador de teste NÃO PAGÁVEL no simulador."
          },
          "pix_qr_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Representação do QR retornada pelo provedor. Pode estar ausente."
          },
          "boleto_url": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "description": "URL HTTPS do boleto retornada pelo provider. Nula no simulador local e em Pix."
          },
          "boleto_digitable_line": {
            "type": [
              "string",
              "null"
            ],
            "description": "Linha digitável como string, sem converter em número. Nula no simulador local e em Pix."
          },
          "boleto_barcode": {
            "type": [
              "string",
              "null"
            ],
            "description": "Código de barras como string. Nulo no simulador local e em Pix."
          },
          "boleto_due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Vencimento YYYY-MM-DD; nulo em Pix."
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_error_code": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]{1,10}$",
            "description": "Código numérico do provider, sanitizado. Nulo quando ausente, inválido ou não capturado no histórico; não inferir motivo a partir de null."
          },
          "provider_error_message": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 400,
            "description": "Orientação estática segura da Calebe Pay, sem Error/Message bruto, tokens ou dados pessoais do provider."
          },
          "provider_http_status": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 100,
            "maximum": 599,
            "description": "Status HTTP observado na resposta do provider, diferente do HTTP da Calebe Pay. Pode ser 200 numa recusa de negócio. Nulo se não houve resposta ou não foi capturado."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "provider_id",
          "amount",
          "currency",
          "method",
          "status",
          "reference",
          "description",
          "environment",
          "simulated",
          "created_at",
          "updated_at"
        ],
        "examples": [
          {
            "id": "txn_exemplo",
            "tenant_id": "ten_exemplo",
            "tenant_name": "Loja Exemplo",
            "provider_id": "prv_simulator",
            "provider_name": "Simulador local — sem movimentação financeira",
            "provider_reference": "sim_txn_exemplo",
            "amount": 1250,
            "currency": "BRL",
            "method": "pix",
            "status": "pending",
            "reference": "pedido-2026-00042",
            "description": "Pedido de demonstração",
            "environment": "sandbox",
            "simulated": true,
            "pix_copy_paste": "CALEBEPAY_SIMULACAO_NAO_PAGAVEL:txn_exemplo",
            "pix_qr_code": null,
            "expires_at": "2026-09-18T15:00:00Z",
            "failure_code": null,
            "created_at": "2026-09-18T14:00:00Z",
            "updated_at": "2026-09-18T14:00:00Z",
            "provider_error_code": null,
            "provider_error_message": null,
            "provider_http_status": null,
            "subaccount_id": null,
            "boleto_url": null,
            "boleto_digitable_line": null,
            "boleto_barcode": null,
            "boleto_due_date": null
          },
          {
            "id": "txn_boleto_exemplo",
            "tenant_id": "ten_exemplo",
            "tenant_name": "Loja Exemplo",
            "provider_id": "prv_simulator",
            "provider_name": "Simulador local — sem movimentação financeira",
            "provider_reference": "sim_txn_boleto_exemplo",
            "amount": 1250,
            "currency": "BRL",
            "method": "boleto",
            "status": "pending",
            "reference": "pedido-boleto-42",
            "description": "Pedido de demonstração",
            "environment": "sandbox",
            "simulated": true,
            "pix_copy_paste": null,
            "pix_qr_code": null,
            "expires_at": null,
            "failure_code": null,
            "created_at": "2026-09-18T14:00:00Z",
            "updated_at": "2026-09-18T14:00:00Z",
            "provider_error_code": null,
            "provider_error_message": null,
            "provider_http_status": null,
            "subaccount_id": null,
            "boleto_url": null,
            "boleto_digitable_line": null,
            "boleto_barcode": null,
            "boleto_due_date": "2026-10-01"
          }
        ]
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": [
              "super_admin",
              "tenant_admin",
              "viewer"
            ]
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "email",
          "role",
          "tenant_id",
          "status"
        ]
      },
      "Session": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "description": "Segredo de sessão; devolvido no login. Validade de 8 horas."
          },
          "user": {
            "$ref": "#/components/schemas/User"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "token",
          "user",
          "expires_at"
        ]
      },
      "Tenant": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "type_id": {
            "type": "string"
          },
          "type_name": {
            "type": "string",
            "description": "Presente na listagem/criação."
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "suspended"
            ]
          },
          "document": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TenantType": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "can_have_children": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Provider": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": [
              "simulator",
              "safe2pay"
            ]
          },
          "environment": {
            "type": "string",
            "enum": [
              "sandbox",
              "production"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "enabled_methods": {
            "type": "array",
            "minItems": 0,
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "pix",
                "boleto"
              ]
            },
            "default": [
              "pix"
            ],
            "description": "Capacidades habilitadas do provider. [] desabilita emissão por todos os métodos. Cadastro existente conserva pix até alteração explícita."
          },
          "is_marketplace": {
            "type": "boolean",
            "default": false,
            "description": "Apenas Safe2Pay. Emissões exigem subconta ativa do tenant exato; nunca herdam a subconta de um ancestral."
          },
          "configured": {
            "type": "boolean",
            "description": "Indica presença de configuração, não validação remota da credencial."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Rule": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "tenant_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_id": {
            "type": "string"
          },
          "provider_name": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "method": {
            "type": "string",
            "enum": [
              "pix",
              "boleto"
            ]
          },
          "priority": {
            "type": "integer"
          },
          "enabled": {
            "type": "boolean"
          },
          "max_amount": {
            "type": "integer",
            "description": "Centavos BRL."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "APIKey": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string",
            "description": "Prefixo identificador; não é a chave completa."
          },
          "scopes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 3,
            "items": {
              "type": "string",
              "enum": [
                "pix:write",
                "boleto:write",
                "transactions:read"
              ]
            },
            "default": [
              "pix:write",
              "transactions:read"
            ],
            "description": "boleto:write exige opt-in explícito; não é concedido a chaves antigas nem no padrão de criação."
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_used_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "APIKeyCreated": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "description": "Segredo exibido apenas nesta resposta. Armazene com segurança."
          },
          "api_key": {
            "$ref": "#/components/schemas/APIKey"
          }
        },
        "required": [
          "key",
          "api_key"
        ]
      },
      "AuditLog": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "actor_id": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "resource_type": {
            "type": "string"
          },
          "resource_id": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Notification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "title": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "severity": {
            "type": "string",
            "enum": [
              "info",
              "warning",
              "error",
              "success"
            ]
          },
          "read_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Summary": {
        "type": "object",
        "properties": {
          "days": {
            "type": "integer",
            "description": "Janela móvel aplicada aos totais de transações e à série.",
            "minimum": 1,
            "maximum": 365,
            "default": 30
          },
          "total_amount": {
            "type": "integer",
            "description": "Centavos, todos os estados, na janela selecionada."
          },
          "paid_amount": {
            "type": "integer",
            "description": "Centavos pagos na janela selecionada."
          },
          "pending_amount": {
            "type": "integer",
            "description": "Centavos pendentes na janela selecionada."
          },
          "total_transactions": {
            "type": "integer",
            "description": "Transações criadas na janela selecionada."
          },
          "success_rate": {
            "type": "number",
            "description": "Percentual das transações da janela com status paid."
          },
          "total_tenants": {
            "type": "integer",
            "description": "Total atual na árvore, independente da janela."
          },
          "active_tenants": {
            "type": "integer",
            "description": "Tenants atualmente ativos na árvore, independente da janela."
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "date": {
                  "type": "string",
                  "description": "Dia em America/Sao_Paulo.",
                  "format": "date"
                },
                "amount": {
                  "type": "integer",
                  "description": "Centavos, todos os estados."
                },
                "count": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "SubaccountAddress": {
        "type": "object",
        "properties": {
          "ZipCode": {
            "type": "string",
            "description": "CEP; normalizado para oito dígitos.",
            "pattern": "^[0-9]{8}$"
          },
          "Street": {
            "type": "string",
            "description": "Até 150 bytes.",
            "minLength": 1,
            "maxLength": 150
          },
          "Number": {
            "type": "string",
            "description": "Número como string.",
            "minLength": 1,
            "maxLength": 15
          },
          "District": {
            "type": "string",
            "minLength": 1,
            "maxLength": 60
          },
          "Complement": {
            "type": "string",
            "maxLength": 150
          },
          "Reference": {
            "type": "string",
            "maxLength": 150
          },
          "CityName": {
            "type": "string",
            "description": "Opcional; o provider resolve a cidade pelo CEP.",
            "maxLength": 120
          },
          "StateInitials": {
            "type": "string",
            "maxLength": 2
          },
          "CountryName": {
            "type": "string",
            "maxLength": 80
          }
        },
        "required": [
          "ZipCode",
          "Street",
          "Number",
          "District"
        ],
        "additionalProperties": false
      },
      "SubaccountBankData": {
        "type": "object",
        "properties": {
          "Bank": {
            "type": "object",
            "properties": {
              "Code": {
                "type": "string",
                "description": "Código do banco como string de um a três dígitos.",
                "pattern": "^[0-9]{1,3}$"
              }
            },
            "required": [
              "Code"
            ],
            "additionalProperties": false
          },
          "AccountType": {
            "type": "object",
            "properties": {
              "Code": {
                "type": "string",
                "description": "Tipo da conta, por exemplo CC.",
                "minLength": 1,
                "maxLength": 8
              }
            },
            "required": [
              "Code"
            ],
            "additionalProperties": false
          },
          "BankAgency": {
            "type": "string",
            "description": "Agência diferente de zero.",
            "pattern": "^[0-9]{1,10}$"
          },
          "BankAgencyDigit": {
            "type": "string",
            "description": "Até um dígito; X permitido somente no Banco do Brasil, código 001.",
            "maxLength": 1
          },
          "BankAccount": {
            "type": "string",
            "description": "Conta diferente de zero.",
            "pattern": "^[0-9]{1,15}$"
          },
          "BankAccountDigit": {
            "type": "string",
            "description": "Até um dígito; X permitido somente no Banco do Brasil.",
            "maxLength": 1
          }
        },
        "required": [
          "Bank",
          "AccountType",
          "BankAgency",
          "BankAccount"
        ],
        "additionalProperties": false
      },
      "SubaccountTax": {
        "type": "object",
        "properties": {
          "TaxTypeName": {
            "type": "string",
            "enum": [
              "1",
              "2"
            ],
            "description": "1: percentual, de 0 a 100. 2: valor em reais, não centavos."
          },
          "Tax": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000000,
            "description": "Taxa contratada; percentual limitado a 100. Não invente taxas nem use amount em centavos neste campo."
          }
        },
        "required": [
          "TaxTypeName",
          "Tax"
        ],
        "additionalProperties": false
      },
      "SubaccountSplit": {
        "type": "object",
        "properties": {
          "PaymentMethodCode": {
            "type": "string",
            "description": "Código do serviço habilitado no marketplace: por exemplo 1 boleto, 6 Pix e 26 repasse. Não repetir no array.",
            "pattern": "^[0-9]{1,3}$"
          },
          "IsSubaccountTaxPayer": {
            "type": "boolean",
            "default": false
          },
          "Taxes": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2,
            "items": {
              "$ref": "#/components/schemas/SubaccountTax"
            },
            "description": "Não repetir TaxTypeName dentro de um método. IsSubaccountTaxPayer=true soma a tarifa Safe2Pay à sobretaxa; false inclui a tarifa Safe2Pay na taxa informada."
          }
        },
        "required": [
          "PaymentMethodCode",
          "Taxes"
        ],
        "additionalProperties": false
      },
      "SubaccountPaymentDate": {
        "type": "object",
        "properties": {
          "PlanFrequence": {
            "type": "object",
            "properties": {
              "Code": {
                "type": "string",
                "enum": [
                  "7",
                  "6",
                  "1"
                ],
                "description": "7 diário; 6 semanal; 1 mensal."
              }
            },
            "required": [
              "Code"
            ],
            "additionalProperties": false
          },
          "PaymentDay": {
            "type": "integer",
            "description": "Omitir para diário; semanal aceita 2 a 6; mensal aceita 1 a 31.",
            "minimum": 1,
            "maximum": 31
          }
        },
        "required": [
          "PlanFrequence"
        ],
        "additionalProperties": false
      },
      "SubaccountRegistration": {
        "type": "object",
        "properties": {
          "Name": {
            "type": "string",
            "description": "Nome PF ou razão social PJ, até 120 bytes.",
            "minLength": 2,
            "maxLength": 120
          },
          "CommercialName": {
            "type": "string",
            "maxLength": 120
          },
          "Identity": {
            "type": "string",
            "description": "CPF com 11 dígitos ou CNPJ com 14 caracteres alfanuméricos. Pontuação normalizada; validação cadastral final no provider."
          },
          "Email": {
            "type": "string",
            "description": "E-mail cadastral, até 254 bytes.",
            "format": "email",
            "maxLength": 254
          },
          "ResponsiblePhone": {
            "type": "string",
            "description": "Telefone de 10 ou 11 dígitos; pontuação é normalizada. Obrigatório na atualização.",
            "pattern": "^[0-9]{10,11}$"
          },
          "TechPhone": {
            "type": "string",
            "description": "Opcional: 10 ou 11 dígitos após normalização.",
            "pattern": "^[0-9]{10,11}$"
          },
          "Address": {
            "$ref": "#/components/schemas/SubaccountAddress"
          },
          "BankData": {
            "$ref": "#/components/schemas/SubaccountBankData"
          },
          "MerchantSplit": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/SubaccountSplit"
            },
            "description": "Na criação, omitir não habilita Pix/boleto. Na atualização, omitir preserva as taxas; enviar substitui toda a configuração, inclusive serviços que ficarem ausentes."
          },
          "IsPanelRestricted": {
            "type": "boolean",
            "default": true,
            "description": "true bloqueia o acesso da subconta ao painel Safe2Pay."
          },
          "IsTransferCheckingAccountDisabled": {
            "type": "boolean",
            "default": false,
            "description": "true desabilita o repasse para a conta bancária cadastrada."
          },
          "WebsiteUrl": {
            "type": "string",
            "maxLength": 2083
          },
          "ResponsibleName": {
            "type": "string",
            "description": "Obrigatório para PJ; PF assume Name quando omitido.",
            "maxLength": 120
          },
          "ResponsibleIdentity": {
            "type": "string",
            "description": "CPF do responsável; obrigatório para PJ. PF assume Identity quando omitido."
          },
          "ResponsibleBirthDate": {
            "type": "string",
            "description": "Nascimento do responsável: não futuro e no máximo 120 anos atrás.",
            "format": "date"
          },
          "TechName": {
            "type": "string",
            "description": "Somente PJ; TechName, TechIdentity e TechEmail devem ser enviados juntos.",
            "maxLength": 120
          },
          "TechIdentity": {
            "type": "string",
            "description": "CPF do responsável técnico."
          },
          "TechEmail": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "MerchantPaymentDate": {
            "$ref": "#/components/schemas/SubaccountPaymentDate"
          }
        },
        "required": [
          "Name",
          "Identity",
          "Email",
          "ResponsibleBirthDate",
          "Address"
        ],
        "additionalProperties": false
      },
      "SubaccountRegistrationUpdate": {
        "type": "object",
        "properties": {
          "Email": {
            "type": "string",
            "description": "E-mail cadastral, até 254 bytes.",
            "format": "email",
            "maxLength": 254
          },
          "ResponsiblePhone": {
            "type": "string",
            "description": "Telefone de 10 ou 11 dígitos; pontuação é normalizada. Obrigatório na atualização.",
            "pattern": "^[0-9]{10,11}$"
          },
          "TechPhone": {
            "type": "string",
            "description": "Opcional: 10 ou 11 dígitos após normalização.",
            "pattern": "^[0-9]{10,11}$"
          },
          "Address": {
            "$ref": "#/components/schemas/SubaccountAddress"
          },
          "BankData": {
            "$ref": "#/components/schemas/SubaccountBankData"
          },
          "MerchantSplit": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/SubaccountSplit"
            },
            "description": "Na criação, omitir não habilita Pix/boleto. Na atualização, omitir preserva as taxas; enviar substitui toda a configuração, inclusive serviços que ficarem ausentes."
          },
          "IsPanelRestricted": {
            "type": "boolean",
            "description": "Opcional. Omitir preserva a configuração atual."
          },
          "IsTransferCheckingAccountDisabled": {
            "type": "boolean",
            "description": "Opcional. Omitir preserva a configuração atual."
          },
          "MerchantPaymentDate": {
            "$ref": "#/components/schemas/SubaccountPaymentDate"
          }
        },
        "required": [
          "Email",
          "ResponsiblePhone"
        ],
        "additionalProperties": false
      },
      "Subaccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID local sub_, diferente do external_id Safe2Pay."
          },
          "tenant_id": {
            "type": "string"
          },
          "tenant_name": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "provider_name": {
            "type": "string"
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ],
            "description": "ID numérico da subconta na Safe2Pay, representado como string."
          },
          "name": {
            "type": "string"
          },
          "document": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "creating",
              "active",
              "unknown",
              "failed"
            ]
          },
          "enabled": {
            "type": "boolean"
          },
          "registration": {
            "type": "object",
            "description": "Cadastro sanitizado. Pode conter dados pessoais e bancários; nunca contém tokens, senhas ou segredos."
          },
          "has_production_token": {
            "type": "boolean",
            "description": "Recalculado da credencial local decifrada e não mascarada; false se ilegível ou mascarada. Não comprova validade remota."
          },
          "has_sandbox_token": {
            "type": "boolean",
            "description": "Recalculado da credencial local decifrada e não mascarada; false se ilegível ou mascarada. Não comprova homologação."
          },
          "last_error_code": {
            "type": [
              "string",
              "null"
            ],
            "description": "Código interno Calebe Pay da última falha."
          },
          "last_provider_error_code": {
            "type": [
              "string",
              "null"
            ],
            "pattern": "^[0-9]{1,10}$",
            "description": "Código Safe2Pay sanitizado, com 1 a 10 dígitos; null quando ausente ou inválido. 301 na criação indica chave sandbox da matriz, exigindo chave de produção para gestão."
          },
          "last_error_message": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 400,
            "description": "Orientação estática sanitizada produzida pela Calebe Pay; nunca copia Error/Message bruto, tokens ou dados pessoais da resposta remota."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "tenant_id",
          "provider_id",
          "external_id",
          "status",
          "enabled",
          "has_production_token",
          "has_sandbox_token"
        ]
      },
      "CreateSubaccount": {
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "registration": {
            "$ref": "#/components/schemas/SubaccountRegistration"
          }
        },
        "required": [
          "tenant_id",
          "provider_id",
          "registration"
        ],
        "additionalProperties": false
      },
      "LinkSubaccount": {
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string"
          },
          "provider_id": {
            "type": "string"
          },
          "external_id": {
            "type": "string",
            "description": "ID numérico remoto positivo como string, até 19 dígitos.",
            "pattern": "^[1-9][0-9]{0,18}$"
          },
          "api_key": {
            "type": "string",
            "description": "Token completo de produção da subconta, conferido contra a consulta autenticada do marketplace. Máscara enviada é 422 validation_error; consulta remota mascarada impede comprovação e retorna 422 subaccount_credentials_unverifiable. Nunca retornado.",
            "writeOnly": true,
            "minLength": 1,
            "maxLength": 8192
          },
          "sandbox_api_key": {
            "type": "string",
            "description": "Token completo e não mascarado de sandbox da subconta; obrigatório se o provider usa sandbox. Não substitui a verificação do token de produção. Nunca retornado.",
            "writeOnly": true,
            "minLength": 1,
            "maxLength": 8192
          }
        },
        "required": [
          "tenant_id",
          "provider_id",
          "external_id",
          "api_key"
        ],
        "additionalProperties": false
      },
      "TransactionRequest": {
        "type": "object",
        "properties": {
          "transaction_id": {
            "type": "string",
            "description": "ID local txn_ da transação consultada."
          },
          "source": {
            "type": "string",
            "enum": [
              "captured",
              "legacy_partial"
            ]
          },
          "request": {
            "type": "object",
            "additionalProperties": true,
            "description": "Corpo normalizado de criação: tenant_id resolvido, valores validados e defaults aplicados. Não preserva bytes, formatação ou campos omitidos do JSON original. Pix capturado inclui expires_in efetivo. Boleto não inclui expires_in e pode omitir opções zero/false. Em legacy_partial, contém somente dados ainda disponíveis, sem inventar opções antigas."
          },
          "provider_request": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Corpo preparado para o provider usando os mesmos builders da emissão, persistido antes da chamada externa. Não comprova envio, aceite ou pagamento. Null para simulador e histórico sem captura; não contém headers, tokens ou chave de idempotência."
          },
          "missing_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Vazio para captured. Legacy Pix: expires_in e provider_request. Legacy boleto: boleto.instruction, boleto.penalty_rate, boleto.interest_rate, boleto.cancel_after_due, boleto.days_before_cancel e provider_request; também boleto.due_date se desconhecido. Ausência não deve ser preenchida com defaults presumidos."
          }
        },
        "required": [
          "transaction_id",
          "source",
          "request",
          "provider_request",
          "missing_fields"
        ],
        "examples": [
          {
            "transaction_id": "txn_simulado",
            "source": "captured",
            "request": {
              "tenant_id": "ten_exemplo",
              "amount": 1250,
              "reference": "pedido-42",
              "description": "Pedido simulado",
              "customer": {
                "name": "Cliente de demonstração",
                "document": "00000000000",
                "email": "cliente@example.com",
                "phone": "11999999999",
                "address": {
                  "zip_code": "01001000",
                  "street": "Rua Exemplo",
                  "number": "100",
                  "district": "Centro",
                  "city": "São Paulo",
                  "state": "SP"
                }
              },
              "expires_in": 3600
            },
            "provider_request": null,
            "missing_fields": []
          },
          {
            "transaction_id": "txn_antigo",
            "source": "legacy_partial",
            "request": {
              "tenant_id": "ten_exemplo",
              "amount": 1250,
              "reference": "pedido-antigo",
              "description": "Pedido histórico",
              "customer": {
                "name": "Cliente de demonstração",
                "document": "00000000000",
                "email": "cliente@example.com"
              }
            },
            "provider_request": null,
            "missing_fields": [
              "expires_in",
              "provider_request"
            ]
          }
        ]
      },
      "UpdateSubaccountCredentials": {
        "type": "object",
        "properties": {
          "api_key": {
            "type": "string",
            "description": "Token completo obtido em canal seguro para o ambiente do provider: Token em production ou TokenSandbox em sandbox. Até 8192 bytes; vazio, máscara, whitespace ou controles são recusados. Apenas armazenamento local, sem comprovar validade remota ou titularidade. Nunca retornado.",
            "writeOnly": true,
            "minLength": 1,
            "maxLength": 8192
          },
          "expected_updated_at": {
            "type": "string",
            "description": "Copie exatamente updated_at do GET local mais recente, preservando as frações do timestamp. Divergência retorna 409 subaccount_changed; não renovar automaticamente para forçar a escrita.",
            "format": "date-time",
            "minLength": 1
          }
        },
        "required": [
          "api_key",
          "expected_updated_at"
        ],
        "additionalProperties": false
      },
      "RemoteSubaccount": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "ID remoto Safe2Pay, não ID local sub_."
          },
          "name": {
            "type": "string"
          },
          "document": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "document",
          "email"
        ]
      },
      "PixCustomer": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nome do pagador; 2 a 120 bytes UTF-8.",
            "minLength": 2,
            "maxLength": 120
          },
          "document": {
            "type": "string",
            "description": "CPF/CNPJ como string; 11 ou 14 caracteres alfanuméricos sem pontuação. Validação de formato, sem conferência de dígitos verificadores.",
            "pattern": "^([A-Za-z0-9]{11}|[A-Za-z0-9]{14})$"
          },
          "email": {
            "type": "string",
            "description": "E-mail do pagador; deve conter @; máximo 254 bytes.",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "description": "Obrigatório para nova cobrança Pix: não vazio, somente dígitos após trim, até 20 bytes no valor bruto. Não há mínimo de 10/11 dígitos.",
            "minLength": 1,
            "maxLength": 20,
            "pattern": "^\\s*[0-9]+\\s*$"
          },
          "address": {
            "$ref": "#/components/schemas/CustomerAddress"
          }
        },
        "required": [
          "name",
          "document",
          "email",
          "phone",
          "address"
        ],
        "additionalProperties": false
      },
      "AdminCreatePix": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "description": "Centavos BRL. 1250 = R$ 12,50.",
            "minimum": 1,
            "maximum": 100000000
          },
          "reference": {
            "type": "string",
            "description": "Correlação com o pedido, não exclusiva.",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "description": "Descrição da cobrança.",
            "minLength": 1,
            "maxLength": 200
          },
          "customer": {
            "$ref": "#/components/schemas/PixCustomer"
          },
          "expires_in": {
            "type": "integer",
            "description": "Expiração em segundos.",
            "minimum": 60,
            "maximum": 86400,
            "default": 3600
          },
          "tenant_id": {
            "type": "string",
            "description": "Obrigatório para super_admin; tenant_admin usa seu tenant por padrão ou um descendente permitido."
          }
        },
        "required": [
          "amount",
          "reference",
          "description",
          "customer"
        ],
        "additionalProperties": false
      },
      "BoletoCustomer": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Nome do pagador; 2 a 120 bytes UTF-8.",
            "minLength": 2,
            "maxLength": 120
          },
          "document": {
            "type": "string",
            "description": "CPF/CNPJ como string; 11 ou 14 caracteres alfanuméricos sem pontuação. Validação de formato, sem conferência de dígitos verificadores.",
            "pattern": "^([A-Za-z0-9]{11}|[A-Za-z0-9]{14})$"
          },
          "email": {
            "type": "string",
            "description": "E-mail do pagador; deve conter @; máximo 254 bytes.",
            "maxLength": 254
          },
          "phone": {
            "type": "string",
            "description": "Telefone obrigatório para boleto; não vazio após trim, até 20 bytes.",
            "minLength": 1,
            "maxLength": 20
          },
          "address": {
            "$ref": "#/components/schemas/CustomerAddress"
          }
        },
        "required": [
          "name",
          "document",
          "email",
          "phone",
          "address"
        ],
        "additionalProperties": false
      },
      "CreateBoleto": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "description": "Centavos BRL. 1250 = R$ 12,50.",
            "minimum": 1,
            "maximum": 100000000
          },
          "reference": {
            "type": "string",
            "description": "Correlação com o pedido, não exclusiva.",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "description": "Descrição da cobrança.",
            "minLength": 1,
            "maxLength": 200
          },
          "customer": {
            "$ref": "#/components/schemas/BoletoCustomer"
          },
          "boleto": {
            "$ref": "#/components/schemas/BoletoOptions"
          }
        },
        "required": [
          "amount",
          "reference",
          "description",
          "customer",
          "boleto"
        ],
        "additionalProperties": false,
        "examples": [
          {
            "amount": 1250,
            "reference": "pedido-boleto-42",
            "description": "Pedido de demonstração",
            "customer": {
              "name": "Cliente de demonstração",
              "document": "00000000000",
              "email": "cliente@example.com",
              "phone": "11999999999",
              "address": {
                "zip_code": "01001000",
                "street": "Rua Exemplo",
                "number": "100",
                "district": "Centro",
                "city": "São Paulo",
                "state": "SP"
              }
            },
            "boleto": {
              "due_date": "2026-10-01",
              "instruction": "Boleto de teste",
              "cancel_after_due": true,
              "days_before_cancel": 1
            }
          }
        ]
      },
      "AdminCreateBoleto": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "integer",
            "description": "Centavos BRL. 1250 = R$ 12,50.",
            "minimum": 1,
            "maximum": 100000000
          },
          "reference": {
            "type": "string",
            "description": "Correlação com o pedido, não exclusiva.",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string",
            "description": "Descrição da cobrança.",
            "minLength": 1,
            "maxLength": 200
          },
          "customer": {
            "$ref": "#/components/schemas/BoletoCustomer"
          },
          "boleto": {
            "$ref": "#/components/schemas/BoletoOptions"
          },
          "tenant_id": {
            "type": "string",
            "description": "Obrigatório para super_admin; tenant_admin usa seu tenant por padrão ou um descendente permitido."
          }
        },
        "required": [
          "amount",
          "reference",
          "description",
          "customer",
          "boleto"
        ],
        "additionalProperties": false
      },
      "WebsiteApplicationInput": {
        "type": "object",
        "properties": {
          "operationMode": {
            "type": "string",
            "enum": [
              "portal-app",
              "api",
              "completo"
            ]
          },
          "selectedProducts": {
            "type": "array",
            "minItems": 1,
            "maxItems": 5,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "pix-in",
                "pix-out",
                "cartoes",
                "cambio",
                "cripto"
              ]
            },
            "description": "Interesses comerciais declarados; não habilita produtos ou pagamentos."
          },
          "monthlyPixVolume": {
            "type": "string"
          },
          "averageTicket": {
            "type": "string"
          },
          "cnpj": {
            "type": "string"
          },
          "legalName": {
            "type": "string"
          },
          "tradeName": {
            "type": "string"
          },
          "businessActivity": {
            "type": "string"
          },
          "website": {
            "type": "string"
          },
          "monthlyRevenue": {
            "type": "string"
          },
          "zipCode": {
            "type": "string"
          },
          "streetAddress": {
            "type": "string"
          },
          "neighborhood": {
            "type": "string"
          },
          "addressNumber": {
            "type": "string"
          },
          "addressComplement": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "state": {
            "type": "string"
          },
          "representativeName": {
            "type": "string"
          },
          "representativeCpf": {
            "type": "string"
          },
          "representativeBirthDate": {
            "type": "string"
          },
          "representativeRole": {
            "type": "string"
          },
          "corporateEmail": {
            "type": "string"
          },
          "mobilePhone": {
            "type": "string"
          },
          "partnerCount": {
            "type": "string"
          },
          "settlementInstitution": {
            "type": "string"
          },
          "settlementAgency": {
            "type": "string"
          },
          "settlementAccount": {
            "type": "string"
          },
          "settlementAccountType": {
            "type": "string"
          },
          "hasBeneficialOwners": {
            "type": "boolean"
          },
          "hasPepRelationship": {
            "type": "boolean"
          },
          "acceptedTerms": {
            "type": "boolean",
            "const": true
          },
          "acceptedPrivacy": {
            "type": "boolean",
            "const": true
          },
          "confirmedAuthority": {
            "type": "boolean",
            "const": true
          },
          "companyUrl": {
            "type": "string",
            "description": "Honeypot; mantenha vazio ou omita."
          }
        },
        "required": [
          "operationMode",
          "selectedProducts",
          "monthlyPixVolume",
          "averageTicket",
          "cnpj",
          "legalName",
          "tradeName",
          "businessActivity",
          "monthlyRevenue",
          "zipCode",
          "streetAddress",
          "neighborhood",
          "addressNumber",
          "city",
          "state",
          "representativeName",
          "representativeCpf",
          "representativeBirthDate",
          "representativeRole",
          "corporateEmail",
          "mobilePhone",
          "partnerCount",
          "settlementInstitution",
          "settlementAgency",
          "settlementAccount",
          "settlementAccountType",
          "acceptedTerms",
          "acceptedPrivacy",
          "confirmedAuthority"
        ],
        "additionalProperties": false
      },
      "WebsiteApplicationCreated": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string",
            "description": "Referência CAL-... para acompanhamento."
          },
          "status": {
            "type": "string",
            "const": "received"
          },
          "next": {
            "type": "string",
            "enum": [
              "/integracao",
              "/calebe-pay"
            ]
          },
          "uploadToken": {
            "type": "string",
            "description": "Credencial exclusiva desta solicitação, devolvida uma única vez; validade de 7 dias. Não é login nem chave financeira."
          }
        },
        "required": [
          "reference",
          "status",
          "next",
          "uploadToken"
        ]
      },
      "WebsiteDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "document_type": {
            "type": "string",
            "enum": [
              "company",
              "representative",
              "address",
              "bank",
              "ownership"
            ]
          },
          "original_name": {
            "type": "string"
          },
          "content_type": {
            "type": "string",
            "enum": [
              "application/pdf",
              "image/jpeg",
              "image/png"
            ]
          },
          "size_bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10485760
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "document_type",
          "original_name",
          "content_type",
          "size_bytes",
          "created_at"
        ]
      },
      "WebsiteApplicationSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "in_review",
              "archived"
            ]
          },
          "operation_mode": {
            "type": "string"
          },
          "legal_name": {
            "type": "string"
          },
          "cnpj": {
            "type": "string"
          },
          "corporate_email": {
            "type": "string"
          },
          "document_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_external_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "creating",
              "active",
              "unknown",
              "failed"
            ]
          },
          "conversion_status": {
            "type": "string",
            "enum": [
              "not_started",
              "creating",
              "converted",
              "unknown",
              "failed"
            ]
          },
          "conversion_retry_allowed": {
            "type": "boolean"
          },
          "conversion_error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "provider_error_code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        },
        "required": [
          "id",
          "reference",
          "status",
          "legal_name",
          "cnpj",
          "corporate_email",
          "document_count",
          "created_at",
          "updated_at"
        ]
      },
      "WebsiteApplicationDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "reference": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "received",
              "in_review",
              "archived"
            ]
          },
          "operation_mode": {
            "type": "string"
          },
          "legal_name": {
            "type": "string"
          },
          "cnpj": {
            "type": "string"
          },
          "corporate_email": {
            "type": "string"
          },
          "document_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 5
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "tenant_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "provider_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_external_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "subaccount_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "creating",
              "active",
              "unknown",
              "failed"
            ]
          },
          "conversion_status": {
            "type": "string",
            "enum": [
              "not_started",
              "creating",
              "converted",
              "unknown",
              "failed"
            ]
          },
          "conversion_retry_allowed": {
            "type": "boolean"
          },
          "conversion_error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "provider_error_code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "payload": {
            "$ref": "#/components/schemas/WebsiteApplicationInput"
          },
          "review_notes": {
            "type": "string",
            "description": "Anotações internas, até 4.000 bytes."
          },
          "documents": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebsiteDocument"
            },
            "maxItems": 5
          },
          "conversion_tenant": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9-]{1,62}$"
              },
              "type_id": {
                "type": "string"
              },
              "parent_id": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "slug",
              "type_id"
            ],
            "additionalProperties": false,
            "description": "Campos imutáveis reservados na primeira tentativa; null antes da conversão."
          }
        },
        "required": [
          "id",
          "reference",
          "status",
          "legal_name",
          "cnpj",
          "corporate_email",
          "document_count",
          "created_at",
          "updated_at",
          "payload",
          "review_notes",
          "documents"
        ]
      },
      "WebsiteConversionInput": {
        "type": "object",
        "properties": {
          "tenant": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9-]{1,62}$"
              },
              "type_id": {
                "type": "string"
              },
              "parent_id": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "required": [
              "name",
              "slug",
              "type_id"
            ],
            "additionalProperties": false
          },
          "provider_id": {
            "type": "string",
            "description": "Provider Safe2Pay marketplace com credencial da matriz."
          },
          "registration": {
            "$ref": "#/components/schemas/SubaccountRegistration"
          }
        },
        "required": [
          "tenant",
          "provider_id",
          "registration"
        ],
        "additionalProperties": false
      },
      "WebsiteConversionResult": {
        "type": "object",
        "properties": {
          "application": {
            "$ref": "#/components/schemas/WebsiteApplicationDetail"
          },
          "tenant_id": {
            "type": "string"
          },
          "subaccount_id": {
            "type": "string"
          },
          "conversion_status": {
            "type": "string",
            "enum": [
              "not_started",
              "creating",
              "converted",
              "unknown",
              "failed"
            ]
          },
          "subaccount_status": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              null,
              "creating",
              "active",
              "unknown",
              "failed"
            ]
          },
          "error": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "code": {
                "type": "string"
              },
              "message": {
                "type": "string"
              },
              "provider_error_code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        },
        "required": [
          "application",
          "tenant_id",
          "subaccount_id",
          "conversion_status",
          "subaccount_status",
          "error"
        ]
      },
      "IntegrationConnection": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "whatsapp",
              "storage"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "smtp",
              "resend",
              "evolution",
              "meta",
              "twilio",
              "minio",
              "s3"
            ]
          },
          "name": {
            "type": "string",
            "minLength": 2,
            "maxLength": 140
          },
          "enabled": {
            "type": "boolean"
          },
          "is_default": {
            "type": "boolean",
            "description": "Máximo de um padrão ativo por canal. Definir outro retira o anterior atomicamente. Desabilitar retira padrão. Configurar padrão não envia mensagens."
          },
          "config": {
            "type": "object",
            "additionalProperties": {
              "type": [
                "string",
                "number",
                "boolean"
              ]
            },
            "description": "Somente campos não secretos do catálogo. SMTP: host,port,security(starttls|tls|none),from_email,from_name. Resend: from_email,from_name. Evolution: base_url,instance. Meta: phone_number_id,api_version. Twilio: account_sid,from_number. MinIO/S3: endpoint,bucket,region,use_ssl,force_path_style. Endpoint S3 deve ser origem HTTP(S) sem caminho/query; use_ssl corresponde ao protocolo. Bucket privado previamente existente. Consulte integrations.md."
          },
          "has_credentials": {
            "type": "boolean"
          },
          "configured_secret_fields": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Nomes de campos secretos preenchidos; nunca valores."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "channel",
          "provider",
          "name",
          "enabled",
          "is_default",
          "config",
          "has_credentials",
          "configured_secret_fields",
          "created_at",
          "updated_at"
        ]
      },
      "IntegrationCatalogEntry": {
        "type": "object",
        "properties": {
          "channel": {
            "type": "string",
            "enum": [
              "email",
              "whatsapp",
              "storage"
            ]
          },
          "provider": {
            "type": "string",
            "enum": [
              "smtp",
              "resend",
              "evolution",
              "meta",
              "twilio",
              "minio",
              "s3"
            ]
          },
          "label": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "key": {
                  "type": "string"
                },
                "label": {
                  "type": "string"
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "text",
                    "password",
                    "number",
                    "boolean",
                    "select"
                  ]
                },
                "secret": {
                  "type": "boolean"
                },
                "required": {
                  "type": "boolean"
                },
                "default": {
                  "type": [
                    "string",
                    "number",
                    "boolean"
                  ]
                },
                "options": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "value": {
                        "type": "string"
                      },
                      "label": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "value",
                      "label"
                    ]
                  }
                }
              },
              "required": [
                "key",
                "label",
                "type",
                "secret",
                "required"
              ]
            }
          }
        },
        "required": [
          "channel",
          "provider",
          "label",
          "fields"
        ]
      }
    }
  }
}
