{
  "openapi": "3.1.0",
  "info": {
    "title": "API do FORSI Chat",
    "version": "1.0.0",
    "description": "Envie mensagens do WhatsApp, leia conversas e contatos e receba eventos por webhook. Autentique com `Authorization: Bearer <chave>` (crie a chave em Configurações → API). Tudo em JSON, UTF-8, só por https."
  },
  "servers": [
    {
      "url": "https://chat.forsi.com.br/api/v1"
    }
  ],
  "security": [
    {
      "chave": []
    }
  ],
  "tags": [
    {
      "name": "Conta"
    },
    {
      "name": "Mensagens"
    },
    {
      "name": "Conversas"
    },
    {
      "name": "Contatos"
    },
    {
      "name": "Modelos"
    },
    {
      "name": "Webhooks"
    },
    {
      "name": "Relatórios"
    },
    {
      "name": "Funil"
    },
    {
      "name": "Agenda"
    },
    {
      "name": "Equipe"
    },
    {
      "name": "Automações"
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "me",
        "tags": [
          "Conta"
        ],
        "summary": "Quem sou eu",
        "description": "A organização, a chave (escopos, validade), os limites e as caixas com o estado das conexões.\n\nQualquer chave válida.",
        "security": [
          {
            "chave": []
          }
        ],
        "responses": {
          "200": {
            "description": "Quem sou eu",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Eu"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/mensagens": {
      "post": {
        "operationId": "enviar_mensagem",
        "tags": [
          "Mensagens"
        ],
        "summary": "Enviar mensagem",
        "description": "Texto, mídia (imagem, vídeo, áudio, documento) ou modelo aprovado. Vai para a fila de envio e responde 202 na hora; acompanhe pelo webhook `mensagem.status` ou por GET /mensagens/{id}. Na API oficial, fora da janela de 24 h só modelo. Envie `Idempotency-Key` ou `id_cliente` (UUID) para identificar o envio.\n\nEscopo: `mensagens:enviar`.",
        "security": [
          {
            "chave": [
              "mensagens:enviar"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id_cliente": {
                    "description": "UUID estável do envio; substitui Idempotency-Key.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "conversa_id": {
                    "description": "Responder numa conversa que já existe. Ou use telefone.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "telefone": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 30,
                    "pattern": "^\\+?[\\d\\s().-]+$",
                    "description": "Com DDI e DDD. Acha o contato com ou sem o 9º dígito.",
                    "example": "+55 31 98888-7777"
                  },
                  "caixa_id": {
                    "description": "Obrigatório quando a organização tem mais de um WhatsApp conectado.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "nome": {
                    "description": "Nome do contato, se ele ainda não tiver.",
                    "type": "string",
                    "maxLength": 120
                  },
                  "tipo": {
                    "default": "texto",
                    "type": "string",
                    "enum": [
                      "texto",
                      "imagem",
                      "video",
                      "audio",
                      "documento",
                      "modelo"
                    ]
                  },
                  "texto": {
                    "description": "Texto (ou legenda da mídia).",
                    "type": "string",
                    "maxLength": 4096
                  },
                  "midia": {
                    "type": "object",
                    "properties": {
                      "url": {
                        "type": "string",
                        "maxLength": 2000,
                        "pattern": "^https:\\/\\/\\S+$",
                        "description": "Link público https do arquivo. O WhatsApp baixa dele na hora do envio."
                      },
                      "mime": {
                        "type": "string",
                        "maxLength": 100,
                        "pattern": "^[a-z]+\\/[a-z0-9.+-]+$"
                      },
                      "nome_arquivo": {
                        "description": "Nome que o contato vê (documentos).",
                        "type": "string",
                        "maxLength": 200
                      }
                    },
                    "required": [
                      "url"
                    ],
                    "additionalProperties": false
                  },
                  "modelo": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "description": "Id do modelo (GET /modelos). Ou use nome + idioma.",
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      "nome": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 512
                      },
                      "idioma": {
                        "example": "pt_BR",
                        "type": "string",
                        "maxLength": 15
                      },
                      "corpo": {
                        "description": "Valores das variáveis do corpo: lista na ordem ({{1}}, {{2}}...) ou objeto por nome.",
                        "anyOf": [
                          {
                            "maxItems": 50,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 1024
                            }
                          },
                          {
                            "type": "object",
                            "propertyNames": {
                              "type": "string",
                              "maxLength": 64
                            },
                            "additionalProperties": {
                              "type": "string",
                              "maxLength": 1024
                            }
                          }
                        ]
                      },
                      "cabecalho": {
                        "type": "object",
                        "properties": {
                          "texto": {
                            "type": "string",
                            "maxLength": 60
                          },
                          "midia": {
                            "type": "object",
                            "properties": {
                              "link": {
                                "type": "string",
                                "maxLength": 2000,
                                "pattern": "^https:\\/\\/\\S+$"
                              },
                              "mime": {
                                "type": "string",
                                "maxLength": 100,
                                "pattern": "^[a-z]+\\/[a-z0-9.+-]+$"
                              }
                            },
                            "required": [
                              "link"
                            ],
                            "additionalProperties": false
                          }
                        },
                        "additionalProperties": false
                      },
                      "botoes": {
                        "description": "Final do link (ou código) por índice do botão: {\"0\": \"abc123\"}.",
                        "type": "object",
                        "propertyNames": {
                          "type": "string",
                          "pattern": "^\\d{1,2}$"
                        },
                        "additionalProperties": {
                          "type": "string",
                          "maxLength": 2000
                        }
                      }
                    },
                    "additionalProperties": false
                  },
                  "responde_a_id": {
                    "description": "Id de uma mensagem desta conversa para citar.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "canal": {
                    "description": "Opcional, só WhatsApp. \"auto\" (padrão, igual a omitir) segue a regra da caixa; \"oficial\" sai só pela API oficial da Meta; \"qr\" sai só pelo WhatsApp por QR. Manual nunca troca de canal: se o escolhido não puder enviar, dá erro.",
                    "type": "string",
                    "enum": [
                      "auto",
                      "oficial",
                      "qr"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Enviar mensagem",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/EnvioAceito"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listar_mensagens_org",
        "tags": [
          "Mensagens"
        ],
        "summary": "Listar mensagens",
        "description": "Mensagens da organização, da mais nova para a mais antiga. Notas internas não aparecem. Filtre por conversa_id ou caixa_id.\n\nEscopo: `mensagens:ler`.",
        "security": [
          {
            "chave": [
              "mensagens:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          },
          {
            "name": "conversa_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listar mensagens",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Mensagem"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/mensagens/{id}": {
      "get": {
        "operationId": "ver_mensagem",
        "tags": [
          "Mensagens"
        ],
        "summary": "Ver uma mensagem",
        "description": "Inclusive o status atual (pendente, enviada, entregue, lida, falhou).\n\nEscopo: `mensagens:ler`.",
        "security": [
          {
            "chave": [
              "mensagens:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma mensagem",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Mensagem"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/mensagens/{id}/midia": {
      "get": {
        "operationId": "baixar_midia",
        "tags": [
          "Mensagens"
        ],
        "summary": "Baixar mídia de uma mensagem",
        "description": "Arquivo binário, com Content-Type original e Content-Disposition. Aceita Range, sem redirecionar. Use item com o id de midia[] ou o índice a partir de zero. Mídia sob demanda retorna 202 midia_baixando com Retry-After; mídia indisponível retorna 409 midia_indisponivel.\n\nEscopo: `mensagens:ler`.",
        "security": [
          {
            "chave": [
              "mensagens:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "item",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Id de midia[] ou índice a partir de zero. Sem item, baixa a primeira mídia.",
              "anyOf": [
                {
                  "type": "string",
                  "format": "uuid",
                  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                },
                {
                  "type": "string",
                  "pattern": "^\\d{1,9}$"
                }
              ]
            },
            "description": "Id de midia[] ou índice a partir de zero. Sem item, baixa a primeira mídia."
          },
          {
            "name": "Range",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "example": "bytes=0-99"
            },
            "description": "Faixa de bytes desejada. O arquivo completo é retornado quando omitido."
          }
        ],
        "responses": {
          "200": {
            "description": "Arquivo de mídia em bytes, com Content-Type e Content-Disposition. Aceita Range (206); um intervalo inválido responde 416.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "Content-Disposition": {
                "description": "Nome sugerido para salvar o arquivo.",
                "schema": {
                  "type": "string"
                }
              },
              "Accept-Ranges": {
                "description": "Indica suporte a Range: bytes.",
                "schema": {
                  "type": "string",
                  "example": "bytes"
                }
              },
              "Content-Range": {
                "description": "Faixa servida em resposta 206.",
                "schema": {
                  "type": "string",
                  "example": "bytes 0-99/200"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "Bytes do arquivo; o tipo real é informado em Content-Type."
                }
              }
            }
          },
          "202": {
            "description": "A mídia está sendo baixada (midia_baixando).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "Retry-After": {
                "description": "Segundos para tentar novamente.",
                "schema": {
                  "type": "integer",
                  "example": 3
                }
              }
            }
          },
          "206": {
            "description": "Arquivo de mídia, limitado à faixa solicitada.",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "Content-Disposition": {
                "description": "Nome sugerido para salvar o arquivo.",
                "schema": {
                  "type": "string"
                }
              },
              "Accept-Ranges": {
                "description": "Indica suporte a Range: bytes.",
                "schema": {
                  "type": "string",
                  "example": "bytes"
                }
              },
              "Content-Range": {
                "description": "Faixa servida e tamanho total.",
                "schema": {
                  "type": "string",
                  "example": "bytes 0-99/200"
                }
              }
            },
            "content": {
              "application/octet-stream": {
                "schema": {
                  "type": "string",
                  "format": "binary",
                  "description": "Bytes do arquivo; o tipo real é informado em Content-Type."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização ou não há mídia.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "A mídia ainda não está disponível para download (midia_indisponivel).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "416": {
            "description": "Intervalo Range inválido ou fora do arquivo.",
            "headers": {
              "Content-Range": {
                "description": "Tamanho total do arquivo quando conhecido.",
                "schema": {
                  "type": "string",
                  "example": "bytes */200"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/conversas": {
      "get": {
        "operationId": "listar_conversas",
        "tags": [
          "Conversas"
        ],
        "summary": "Listar conversas",
        "description": "Da mais recente para a mais antiga, paginado por cursor.\n\nEscopo: `conversas:ler`.",
        "security": [
          {
            "chave": [
              "conversas:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "aberta",
                "pendente",
                "adiada",
                "resolvida"
              ]
            }
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "contato_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "telefone",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 30,
              "pattern": "^\\+?[\\d\\s().-]+$",
              "description": "Com DDI e DDD. Acha o contato com ou sem o 9º dígito.",
              "example": "+55 31 98888-7777"
            },
            "description": "Com DDI e DDD. Acha o contato com ou sem o 9º dígito."
          },
          {
            "name": "desde",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só conversas atualizadas a partir desta data (ISO 8601).",
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
            },
            "description": "Só conversas atualizadas a partir desta data (ISO 8601)."
          },
          {
            "name": "anuncio",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só conversas que vieram de anúncio: `1` para qualquer anúncio ou o id de um anúncio.",
              "type": "string",
              "pattern": "^(1|true|\\d{1,30})$"
            },
            "description": "Só conversas que vieram de anúncio: `1` para qualquer anúncio ou o id de um anúncio."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar conversas",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversa"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/conversas/{id}": {
      "get": {
        "operationId": "ver_conversa",
        "tags": [
          "Conversas"
        ],
        "summary": "Ver uma conversa",
        "description": "Escopo: `conversas:ler`.",
        "security": [
          {
            "chave": [
              "conversas:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma conversa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Conversa"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/conversas/{id}/mensagens": {
      "get": {
        "operationId": "listar_mensagens",
        "tags": [
          "Conversas"
        ],
        "summary": "Mensagens de uma conversa",
        "description": "Da mais nova para a mais antiga. Notas internas da equipe não aparecem.\n\nEscopo: `mensagens:ler`.",
        "security": [
          {
            "chave": [
              "mensagens:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Mensagens de uma conversa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Mensagem"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/contatos": {
      "get": {
        "operationId": "listar_contatos",
        "tags": [
          "Contatos"
        ],
        "summary": "Listar e buscar contatos",
        "description": "Busca por telefone acha com e sem o 9º dígito.\n\nEscopo: `contatos:ler`.",
        "security": [
          {
            "chave": [
              "contatos:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "busca",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Parte do nome ou do telefone, ou o e-mail exato.",
              "type": "string",
              "maxLength": 100
            },
            "description": "Parte do nome ou do telefone, ou o e-mail exato."
          },
          {
            "name": "telefone",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 30,
              "pattern": "^\\+?[\\d\\s().-]+$",
              "description": "Com DDI e DDD. Acha o contato com ou sem o 9º dígito.",
              "example": "+55 31 98888-7777"
            },
            "description": "Com DDI e DDD. Acha o contato com ou sem o 9º dígito."
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 254
            }
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar e buscar contatos",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Contato"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_contato",
        "tags": [
          "Contatos"
        ],
        "summary": "Criar contato",
        "description": "Telefone repetido (com ou sem o 9) dá 409.\n\nEscopo: `contatos:escrever`.",
        "security": [
          {
            "chave": [
              "contatos:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 120
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "telefone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 30
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 254
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "instagram": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 31
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "campos": {
                    "description": "Campos personalizados (objeto livre, até 16 mil caracteres).",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 64
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar contato",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Contato"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/contatos/{id}": {
      "get": {
        "operationId": "ver_contato",
        "tags": [
          "Contatos"
        ],
        "summary": "Ver um contato",
        "description": "Contato mesclado responde com o que ficou.\n\nEscopo: `contatos:ler`.",
        "security": [
          {
            "chave": [
              "contatos:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um contato",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Contato"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_contato",
        "tags": [
          "Contatos"
        ],
        "summary": "Atualizar contato",
        "description": "Só os campos enviados mudam; null apaga o campo.\n\nEscopo: `contatos:escrever`.",
        "security": [
          {
            "chave": [
              "contatos:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 120
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "telefone": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 30
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "email": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 254
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "instagram": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 31
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "campos": {
                    "description": "Campos personalizados (objeto livre, até 16 mil caracteres).",
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "maxLength": 64
                    },
                    "additionalProperties": {}
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar contato",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Contato"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_contato",
        "tags": [
          "Contatos"
        ],
        "summary": "Apagar contato",
        "description": "Apaga o contato e as conversas dele. Não tem volta.\n\nEscopo: `contatos:escrever`.",
        "security": [
          {
            "chave": [
              "contatos:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar contato",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Apagado"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/modelos": {
      "get": {
        "operationId": "listar_modelos",
        "tags": [
          "Modelos"
        ],
        "summary": "Listar modelos do WhatsApp",
        "description": "Modelos da API oficial sincronizados com a Meta, com as variáveis de cada um.\n\nEscopo: `modelos:ler`.",
        "security": [
          {
            "chave": [
              "modelos:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "schema": {
              "description": "APPROVED, PENDING, REJECTED...",
              "type": "string",
              "maxLength": 30,
              "pattern": "^[A-Za-z_]+$"
            },
            "description": "APPROVED, PENDING, REJECTED..."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Listar modelos do WhatsApp",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Modelo"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listar_webhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "Listar webhooks",
        "description": "Escopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Listar webhooks",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Webhook"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Criar webhook",
        "description": "Responde com `segredo` UMA vez: guarde para conferir a assinatura `X-Forsi-Signature`. Repetir com a mesma `Idempotency-Key` devolve o webhook sem `segredo` e sem criar outro.\n\nEscopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "url": {
                    "type": "string",
                    "maxLength": 2000,
                    "pattern": "^https:\\/\\/\\S+$",
                    "description": "https, porta 443, nome público (sem IP, sem rede interna)."
                  },
                  "eventos": {
                    "minItems": 1,
                    "maxItems": 19,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "mensagem.recebida",
                        "mensagem.enviada",
                        "mensagem.status",
                        "conversa.criada",
                        "conversa.atribuida",
                        "conversa.encerrada",
                        "contato.criado",
                        "negocio.criado",
                        "negocio.movido",
                        "negocio.ganho",
                        "negocio.perdido",
                        "agendamento.criado",
                        "agendamento.remarcado",
                        "agendamento.cancelado",
                        "agendamento.confirmado",
                        "membro.convidado",
                        "membro.entrou",
                        "membro.alterado",
                        "membro.removido"
                      ]
                    }
                  }
                },
                "required": [
                  "nome",
                  "url",
                  "eventos"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar webhook",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/WebhookComSegredo"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "operationId": "ver_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Ver um webhook",
        "description": "Escopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um webhook",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Atualizar webhook",
        "description": "Mude nome, URL, eventos, ou pause/reative.\n\nEscopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "url": {
                    "type": "string",
                    "maxLength": 2000,
                    "pattern": "^https:\\/\\/\\S+$"
                  },
                  "eventos": {
                    "minItems": 1,
                    "maxItems": 19,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "mensagem.recebida",
                        "mensagem.enviada",
                        "mensagem.status",
                        "conversa.criada",
                        "conversa.atribuida",
                        "conversa.encerrada",
                        "contato.criado",
                        "negocio.criado",
                        "negocio.movido",
                        "negocio.ganho",
                        "negocio.perdido",
                        "agendamento.criado",
                        "agendamento.remarcado",
                        "agendamento.cancelado",
                        "agendamento.confirmado",
                        "membro.convidado",
                        "membro.entrou",
                        "membro.alterado",
                        "membro.removido"
                      ]
                    }
                  },
                  "ativo": {
                    "description": "false pausa; true reativa (zera as falhas).",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar webhook",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Webhook"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Apagar webhook",
        "description": "Escopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar webhook",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Apagado"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/rotacionar": {
      "post": {
        "operationId": "rotacionar_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Trocar o segredo",
        "description": "Gera um segredo novo (mostrado uma vez; repetir com a mesma `Idempotency-Key` não gira de novo nem repete o segredo). Durante a graça as entregas levam as duas assinaturas.\n\nEscopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "horas": {
                    "description": "Quanto tempo o segredo antigo ainda assina junto (0 a 168, padrão 24).",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 168
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Trocar o segredo",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/WebhookComSegredo"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/testar": {
      "post": {
        "operationId": "testar_webhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Mandar um evento de teste",
        "description": "Escopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Mandar um evento de teste",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/TesteAceito"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}/entregas": {
      "get": {
        "operationId": "listar_entregas",
        "tags": [
          "Webhooks"
        ],
        "summary": "Histórico de entregas",
        "description": "50 por página, da mais nova para a mais antiga, com o corpo enviado e a resposta.\n\nEscopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "pendente",
                "falhou",
                "entregue",
                "morta",
                "cancelada"
              ]
            }
          },
          {
            "name": "antes",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Id da última entrega vista (página seguinte).",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Id da última entrega vista (página seguinte)."
          }
        ],
        "responses": {
          "200": {
            "description": "Histórico de entregas",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Entrega"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/entregas/{id}/reenviar": {
      "post": {
        "operationId": "reenviar_entrega",
        "tags": [
          "Webhooks"
        ],
        "summary": "Reenviar uma entrega",
        "description": "Escopo: `webhooks:gerir`.",
        "security": [
          {
            "chave": [
              "webhooks:gerir"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Reenviar uma entrega",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Entrega"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/funis": {
      "get": {
        "operationId": "listar_funis",
        "tags": [
          "Funil"
        ],
        "summary": "Listar funis",
        "description": "Cada funil vem com as etapas, na ordem do quadro.\n\nEscopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Listar funis",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Funil"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_funil",
        "tags": [
          "Funil"
        ],
        "summary": "Criar funil",
        "description": "Até 20 funis e 30 etapas por funil. Sem `etapas`, usa o modelo do segmento. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  },
                  "etapas": {
                    "description": "Sem etapas, o funil nasce com o modelo do segmento da organização. Precisa de pelo menos uma etapa que não seja de ganho nem de perda.",
                    "minItems": 1,
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "nome": {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 40
                        },
                        "cor": {
                          "type": "string",
                          "enum": [
                            "slate",
                            "blue",
                            "violet",
                            "amber",
                            "emerald",
                            "green",
                            "rose",
                            "cyan",
                            "orange"
                          ]
                        },
                        "ganha": {
                          "description": "Etapa de ganho: negócio que chega aqui vira ganho.",
                          "type": "boolean"
                        },
                        "perdida": {
                          "description": "Etapa de perda: negócio que chega aqui vira perdido.",
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "nome"
                      ],
                      "additionalProperties": false
                    }
                  }
                },
                "required": [
                  "nome"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar funil",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Funil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/funis/{id}": {
      "get": {
        "operationId": "ver_funil",
        "tags": [
          "Funil"
        ],
        "summary": "Ver um funil",
        "description": "Escopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um funil",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Funil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_funil",
        "tags": [
          "Funil"
        ],
        "summary": "Renomear funil",
        "description": "Só o nome muda; etapas se mexem em /etapas.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 60
                  }
                },
                "required": [
                  "nome"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Renomear funil",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Funil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_funil",
        "tags": [
          "Funil"
        ],
        "summary": "Apagar funil",
        "description": "Apaga o funil, as etapas e TODOS os negócios dele. Não tem volta. O último funil não pode ser apagado. Escopo próprio, separado de `funil:escrever`.\n\nEscopo: `funil:apagar`.",
        "security": [
          {
            "chave": [
              "funil:apagar"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar funil",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoFunil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/etapas": {
      "post": {
        "operationId": "criar_etapa",
        "tags": [
          "Funil"
        ],
        "summary": "Criar etapa",
        "description": "Informe `funil_id`. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "funil_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "ganha": {
                    "type": "boolean"
                  },
                  "perdida": {
                    "type": "boolean"
                  },
                  "posicao": {
                    "description": "Posição no funil, a partir de 0. Sem isso vai para o fim.",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 30
                  }
                },
                "required": [
                  "funil_id",
                  "nome"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar etapa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Etapa"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/etapas/{id}": {
      "get": {
        "operationId": "ver_etapa",
        "tags": [
          "Funil"
        ],
        "summary": "Ver uma etapa",
        "description": "Escopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma etapa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Etapa"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_etapa",
        "tags": [
          "Funil"
        ],
        "summary": "Atualizar etapa",
        "description": "Nome, cor, tipo (ganho/perda) e posição. O funil precisa manter pelo menos uma etapa aberta.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "ganha": {
                    "type": "boolean"
                  },
                  "perdida": {
                    "type": "boolean"
                  },
                  "posicao": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 30
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar etapa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Etapa"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_etapa",
        "tags": [
          "Funil"
        ],
        "summary": "Apagar etapa",
        "description": "Os negócios da etapa mudam para `destino_id` (ou para a primeira etapa aberta) e voltam a \"aberto\". Escopo próprio, separado de `funil:escrever`.\n\nEscopo: `funil:apagar`.",
        "security": [
          {
            "chave": [
              "funil:apagar"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "destino_id": {
                    "description": "Etapa do mesmo funil que recebe os negócios. Sem isso vão para a primeira etapa aberta.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Apagar etapa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoFunil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios": {
      "get": {
        "operationId": "listar_negocios",
        "tags": [
          "Funil"
        ],
        "summary": "Listar negócios",
        "description": "Do mais novo para o mais antigo, paginado por cursor. Filtre por funil, etapa, contato, responsável, estado ou título.\n\nEscopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "funil_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "etapa_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "contato_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "responsavel_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "aberto",
                "ganho",
                "perdido"
              ]
            }
          },
          {
            "name": "busca",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Parte do título.",
              "type": "string",
              "maxLength": 100
            },
            "description": "Parte do título."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar negócios",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Negocio"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Criar negócio",
        "description": "Mesmo efeito de criar pelo quadro: aparece na tela em tempo real, entra no histórico da conversa e dispara `negocio.criado`. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "titulo": {
                    "description": "Sem título, usa o nome do contato.",
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 160
                  },
                  "funil_id": {
                    "description": "Sem funil nem etapa, vai para o primeiro funil.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "etapa_id": {
                    "description": "Sem etapa, entra na primeira etapa aberta do funil.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "contato_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "conversa_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "responsavel_id": {
                    "description": "Id de um membro da equipe (veja GET /me).",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "valor_centavos": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000000000,
                    "description": "Valor em centavos (R$ 1.500,00 = 150000)."
                  },
                  "previsao": {
                    "description": "Data prevista de fechamento (AAAA-MM-DD).",
                    "type": "string",
                    "format": "date",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}": {
      "get": {
        "operationId": "ver_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Ver um negócio",
        "description": "Escopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Atualizar negócio",
        "description": "Título, valor, responsável, previsão, contato. Para mudar de etapa use /mover, /ganhar ou /perder.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "titulo": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 160
                  },
                  "valor_centavos": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000000000,
                    "description": "Valor em centavos (R$ 1.500,00 = 150000)."
                  },
                  "responsavel_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contato_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "previsao": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "motivo_perda": {
                    "description": "Só vale em negócio perdido.",
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 300
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Apagar negócio",
        "description": "Apaga o negócio e as notas dele. Não tem volta. Escopo próprio, separado de `funil:escrever`.\n\nEscopo: `funil:apagar`.",
        "security": [
          {
            "chave": [
              "funil:apagar"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoFunil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}/mover": {
      "post": {
        "operationId": "mover_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Mover para outra etapa",
        "description": "O mesmo que arrastar no quadro. Cair numa etapa de ganho ou de perda marca o negócio como ganho ou perdido; dispara `negocio.movido` (e `negocio.ganho` / `negocio.perdido`).\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "etapa_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "posicao": {
                    "description": "Ordem dentro da etapa (menor = mais acima). Sem isso vai para o fim da coluna.",
                    "type": "number",
                    "minimum": -1000000000000,
                    "maximum": 1000000000000
                  },
                  "motivo": {
                    "description": "Motivo da perda, se a etapa for de perda.",
                    "type": "string",
                    "maxLength": 300
                  }
                },
                "required": [
                  "etapa_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mover para outra etapa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}/ganhar": {
      "post": {
        "operationId": "ganhar_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Marcar como ganho",
        "description": "Move para a primeira etapa de ganho do funil.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Marcar como ganho",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}/perder": {
      "post": {
        "operationId": "perder_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Marcar como perdido",
        "description": "Move para a primeira etapa de perda do funil. `motivo` é opcional.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "motivo": {
                    "type": "string",
                    "maxLength": 300
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Marcar como perdido",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}/reabrir": {
      "post": {
        "operationId": "reabrir_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Reabrir negócio",
        "description": "Volta para a primeira etapa aberta do funil.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reabrir negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Negocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/{id}/notas": {
      "get": {
        "operationId": "listar_notas_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Notas de um negócio",
        "description": "Da mais nova para a mais antiga.\n\nEscopo: `funil:ler`.",
        "security": [
          {
            "chave": [
              "funil:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "Valor de `proximo` da página anterior."
            },
            "description": "Valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Notas de um negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/NotaNegocio"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_nota_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Anotar no negócio",
        "description": "Até 500 notas por negócio. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `funil:escrever`.",
        "security": [
          {
            "chave": [
              "funil:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "texto": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": [
                  "texto"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Anotar no negócio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/NotaNegocio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/negocios/notas/{id}": {
      "delete": {
        "operationId": "apagar_nota_negocio",
        "tags": [
          "Funil"
        ],
        "summary": "Apagar uma nota",
        "description": "O `id` é o da nota. Escopo próprio, separado de `funil:escrever`.\n\nEscopo: `funil:apagar`.",
        "security": [
          {
            "chave": [
              "funil:apagar"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar uma nota",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoFunil"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/volume": {
      "get": {
        "operationId": "relatorio_volume",
        "tags": [
          "Relatórios"
        ],
        "summary": "Volume de conversas e mensagens",
        "description": "Conversas novas e resolvidas e mensagens recebidas/enviadas no período, em uma linha por dia, semana ou mês, mais o movimento por hora do dia. Os mesmos números da tela Relatórios.\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "granularidade",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`.",
              "type": "string",
              "enum": [
                "dia",
                "semana",
                "mes"
              ]
            },
            "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Volume de conversas e mensagens",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioVolume"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/tempo-de-resposta": {
      "get": {
        "operationId": "relatorio_tempo_de_resposta",
        "tags": [
          "Relatórios"
        ],
        "summary": "Tempo de resposta e de resolução",
        "description": "Primeira resposta e resolução das conversas: quantidade, mediana, 90% das conversas, faixas e a porcentagem respondida em até 1, 5, 15 e 60 minutos. Tempos em segundos. Por semana ou mês, a mediana é calculada de novo em cada período (não é média de medianas).\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "granularidade",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`.",
              "type": "string",
              "enum": [
                "dia",
                "semana",
                "mes"
              ]
            },
            "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Tempo de resposta e de resolução",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioTempo"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/atendentes": {
      "get": {
        "operationId": "relatorio_atendentes",
        "tags": [
          "Relatórios"
        ],
        "summary": "Desempenho por atendente",
        "description": "Uma linha por pessoa da equipe com conversas atendidas, mensagens enviadas, resolvidas, abertas agora e tempo de primeira resposta no período todo.\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Desempenho por atendente",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioAtendentes"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/caixas": {
      "get": {
        "operationId": "relatorio_caixas",
        "tags": [
          "Relatórios"
        ],
        "summary": "Desempenho por caixa (canal)",
        "description": "Uma linha por caixa (WhatsApp, Instagram etc.) com conversas novas e resolvidas e mensagens no período todo.\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Desempenho por caixa (canal)",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioCaixas"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/agente-de-ia": {
      "get": {
        "operationId": "relatorio_agente_de_ia",
        "tags": [
          "Relatórios"
        ],
        "summary": "Atendimento do agente de IA",
        "description": "Quantas conversas o agente resolveu sozinho, quantas passou para a equipe e os motivos da passagem.\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "caixa_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só os números desta caixa (WhatsApp, Instagram...). Veja as caixas em GET /me."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Atendimento do agente de IA",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioAgenteDeIa"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/relatorios/creditos": {
      "get": {
        "operationId": "relatorio_creditos",
        "tags": [
          "Relatórios"
        ],
        "summary": "Créditos de IA usados",
        "description": "Créditos gastos no período (por dia, semana ou mês e por tipo de uso) e o saldo atual. Só créditos: nada em dinheiro.\n\nEscopo: `relatorios:ler`.",
        "security": [
          {
            "chave": [
              "relatorios:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Primeiro dia (AAAA-MM-DD, no fuso da organização). Padrão: 29 dias antes de `ate`."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias.",
              "type": "string",
              "format": "date",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
            },
            "description": "Último dia, inclusive. Padrão: hoje. O período vai até 366 dias."
          },
          {
            "name": "granularidade",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`.",
              "type": "string",
              "enum": [
                "dia",
                "semana",
                "mes"
              ]
            },
            "description": "Tamanho de cada linha da série: `dia` (padrão), `semana` (começa na segunda) ou `mes`."
          },
          {
            "name": "formato",
            "in": "query",
            "required": false,
            "schema": {
              "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha).",
              "type": "string",
              "enum": [
                "json",
                "csv"
              ]
            },
            "description": "`json` (padrão) ou `csv` (UTF-8 com BOM, separado por vírgula, pronto para planilha)."
          }
        ],
        "responses": {
          "200": {
            "description": "Créditos de IA usados",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              },
              "ETag": {
                "description": "Mande em If-None-Match para receber 304 se nada mudou.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RelatorioCreditos"
                    }
                  }
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string",
                  "description": "Com ?formato=csv: uma linha por item de `linhas`, colunas fixas, UTF-8 com BOM."
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/agendas": {
      "get": {
        "operationId": "listar_agendas",
        "tags": [
          "Agenda"
        ],
        "summary": "Listar agendas",
        "description": "As agendas (uma por profissional ou sala), com horário de trabalho, duração padrão e fuso.\n\nEscopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          },
          {
            "name": "ativa",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só as ativas (`true`) ou só as inativas (`false`).",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "Só as ativas (`true`) ou só as inativas (`false`)."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar agendas",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agenda"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_agenda",
        "tags": [
          "Agenda"
        ],
        "summary": "Criar agenda",
        "description": "Até 100 agendas por organização. Mande `Idempotency-Key` para poder repetir com segurança. Apagar agenda não existe na API.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "fuso": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "Fuso IANA, ex.: America/Sao_Paulo. Padrão: o da organização."
                  },
                  "horario": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[0-6]$"
                    },
                    "additionalProperties": {
                      "maxItems": 8,
                      "type": "array",
                      "items": {
                        "type": "array",
                        "prefixItems": [
                          {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          }
                        ]
                      }
                    },
                    "description": "Horário de trabalho: dia da semana (0 domingo a 6 sábado) para faixas [início, fim], ex.: {\"1\": [[\"09:00\",\"12:00\"],[\"14:00\",\"18:00\"]]}."
                  },
                  "duracao_min": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 720,
                    "description": "Duração padrão de cada compromisso, em minutos (5 a 720)."
                  },
                  "intervalo_min": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 240,
                    "description": "Folga entre compromissos, em minutos (0 a 240)."
                  },
                  "antecedencia_min": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 43200,
                    "description": "Antecedência mínima para marcar, em minutos."
                  },
                  "lembretes": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "antes_min": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 43200
                        }
                      },
                      "required": [
                        "antes_min"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Lembretes ao contato: até 5, cada um com `antes_min` (minutos antes do compromisso)."
                  },
                  "mensagem_lembrete": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "ativa": {
                    "type": "boolean"
                  },
                  "usuario_id": {
                    "description": "Profissional dono da agenda (precisa ser da equipe). Só na criação; não dá para trocar depois pela API.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  }
                },
                "required": [
                  "nome"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar agenda",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Agenda"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/agendas/{id}": {
      "get": {
        "operationId": "ver_agenda",
        "tags": [
          "Agenda"
        ],
        "summary": "Ver uma agenda",
        "description": "Escopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma agenda",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Agenda"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_agenda",
        "tags": [
          "Agenda"
        ],
        "summary": "Atualizar agenda",
        "description": "Horário, duração, intervalo, antecedência, fuso, lembretes, cor, nome e `ativa`. Para tirar uma agenda do ar, use `ativa: false`. Trocar o profissional só pela tela.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "fuso": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "description": "Fuso IANA, ex.: America/Sao_Paulo. Padrão: o da organização."
                  },
                  "horario": {
                    "type": "object",
                    "propertyNames": {
                      "type": "string",
                      "pattern": "^[0-6]$"
                    },
                    "additionalProperties": {
                      "maxItems": 8,
                      "type": "array",
                      "items": {
                        "type": "array",
                        "prefixItems": [
                          {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          },
                          {
                            "type": "string",
                            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$"
                          }
                        ]
                      }
                    },
                    "description": "Horário de trabalho: dia da semana (0 domingo a 6 sábado) para faixas [início, fim], ex.: {\"1\": [[\"09:00\",\"12:00\"],[\"14:00\",\"18:00\"]]}."
                  },
                  "duracao_min": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 720,
                    "description": "Duração padrão de cada compromisso, em minutos (5 a 720)."
                  },
                  "intervalo_min": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 240,
                    "description": "Folga entre compromissos, em minutos (0 a 240)."
                  },
                  "antecedencia_min": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 43200,
                    "description": "Antecedência mínima para marcar, em minutos."
                  },
                  "lembretes": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "antes_min": {
                          "type": "integer",
                          "minimum": 1,
                          "maximum": 43200
                        }
                      },
                      "required": [
                        "antes_min"
                      ],
                      "additionalProperties": false
                    },
                    "description": "Lembretes ao contato: até 5, cada um com `antes_min` (minutos antes do compromisso)."
                  },
                  "mensagem_lembrete": {
                    "type": "string",
                    "maxLength": 1000
                  },
                  "ativa": {
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar agenda",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Agenda"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/disponibilidade": {
      "get": {
        "operationId": "disponibilidade",
        "tags": [
          "Agenda"
        ],
        "summary": "Horários livres",
        "description": "Os mesmos horários que o agente de IA oferece: respeita o horário de trabalho, bloqueios, compromissos, intervalo e antecedência mínima. Cada horário traz `inicio`/`fim` em UTC e `inicio_local`/`fim_local` no fuso da agenda. Até 400 horários por consulta.\n\nEscopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Começo da janela (com fuso)."
            },
            "description": "Começo da janela (com fuso)."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Fim da janela (com fuso). A janela vai até 62 dias."
            },
            "description": "Fim da janela (com fuso). A janela vai até 62 dias."
          },
          {
            "name": "agenda_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só esta agenda. Sem ela, todas as agendas ativas.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só esta agenda. Sem ela, todas as agendas ativas."
          },
          {
            "name": "duracao_min",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Duração do compromisso, em minutos. Padrão: a da agenda.",
              "type": "integer",
              "minimum": 5,
              "maximum": 720
            },
            "description": "Duração do compromisso, em minutos. Padrão: a da agenda."
          }
        ],
        "responses": {
          "200": {
            "description": "Horários livres",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Disponibilidade"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/compromissos": {
      "get": {
        "operationId": "listar_compromissos",
        "tags": [
          "Agenda"
        ],
        "summary": "Listar compromissos",
        "description": "Em ordem de horário, paginado por cursor. Filtre por agenda, contato, estado e período.\n\nEscopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          },
          {
            "name": "agenda_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "contato_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "estado",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "marcado",
                "confirmado",
                "concluido",
                "faltou",
                "cancelado"
              ]
            }
          },
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Só compromissos que terminam depois disto."
            },
            "description": "Só compromissos que terminam depois disto."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Só compromissos que começam antes disto."
            },
            "description": "Só compromissos que começam antes disto."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar compromissos",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Compromisso"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Marcar compromisso",
        "description": "Mesmas regras do app e do agente: horário de trabalho, bloqueios, intervalo e antecedência mínima. Horário ocupado devolve 409, mesmo com várias chamadas ao mesmo tempo. O contato vem de `contato_id`, `conversa_id` ou `telefone` (um só). Não existe `forcar`: encaixe fora das regras só pela tela. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inicio": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Começo do compromisso (com fuso)."
                  },
                  "fim": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Fim do compromisso (com fuso, até 12 horas depois do início)."
                  },
                  "duracao_min": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 720,
                    "description": "Duração em minutos (5 a 720)."
                  },
                  "agenda_id": {
                    "description": "Sem ela, vale a primeira agenda com o horário livre (como o agente faz).",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "titulo": {
                    "type": "string",
                    "maxLength": 160
                  },
                  "local": {
                    "type": "string",
                    "maxLength": 200
                  },
                  "link": {
                    "type": "string",
                    "maxLength": 500,
                    "pattern": "^https:\\/\\/\\S+$",
                    "description": "Link da chamada ou reunião (https)."
                  },
                  "notas": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "contato_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "conversa_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "telefone": {
                    "description": "Acha o contato pelo telefone (ou cria um). Não combine com `contato_id` nem `conversa_id`.",
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 30,
                    "pattern": "^\\+?[0-9 ()-]+$"
                  },
                  "nome": {
                    "description": "Nome do contato novo, quando criado pelo `telefone`.",
                    "type": "string",
                    "maxLength": 120
                  }
                },
                "required": [
                  "inicio"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Marcar compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/compromissos/{id}": {
      "get": {
        "operationId": "ver_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Ver um compromisso",
        "description": "Escopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Atualizar compromisso",
        "description": "Título, notas, local, link, contato e `estado` (só `concluido` ou `faltou`, para marcar comparecimento). Horário: use remarcar.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "titulo": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 160
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "local": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 200
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "link": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 500,
                        "pattern": "^https:\\/\\/\\S+$",
                        "description": "Link da chamada ou reunião (https)."
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "notas": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "contato_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "estado": {
                    "description": "Só para encerrar: `concluido` (compareceu) ou `faltou`. Confirmar e cancelar têm rota própria.",
                    "type": "string",
                    "enum": [
                      "concluido",
                      "faltou"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/compromissos/{id}/remarcar": {
      "post": {
        "operationId": "remarcar_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Remarcar compromisso",
        "description": "Só compromissos marcados ou confirmados. Volta para `marcado` e dispara `agendamento.remarcado`. Cancelado ou encerrado devolve 409.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inicio": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Novo começo (com fuso)."
                  },
                  "fim": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Novo fim (com fuso)."
                  },
                  "duracao_min": {
                    "type": "integer",
                    "minimum": 5,
                    "maximum": 720,
                    "description": "Duração em minutos (5 a 720)."
                  },
                  "agenda_id": {
                    "description": "Mudar de agenda junto com o horário.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  }
                },
                "required": [
                  "inicio"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Remarcar compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/compromissos/{id}/cancelar": {
      "post": {
        "operationId": "cancelar_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Cancelar compromisso",
        "description": "Libera o horário. Repetir o cancelamento é seguro. Não apaga o registro.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Cancelar compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/compromissos/{id}/confirmar": {
      "post": {
        "operationId": "confirmar_compromisso",
        "tags": [
          "Agenda"
        ],
        "summary": "Confirmar compromisso",
        "description": "O contato confirmou presença.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {},
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Confirmar compromisso",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Compromisso"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/bloqueios": {
      "get": {
        "operationId": "listar_bloqueios",
        "tags": [
          "Agenda"
        ],
        "summary": "Listar bloqueios",
        "description": "Folgas, almoços e feriados que fecham a agenda. Os que repetem aparecem uma vez, com a regra de repetição.\n\nEscopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          },
          {
            "name": "agenda_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            }
          },
          {
            "name": "de",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Só bloqueios que ainda valem a partir daqui."
            },
            "description": "Só bloqueios que ainda valem a partir daqui."
          },
          {
            "name": "ate",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
              "description": "Só bloqueios que começam antes disto."
            },
            "description": "Só bloqueios que começam antes disto."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar bloqueios",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Bloqueio"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_bloqueio",
        "tags": [
          "Agenda"
        ],
        "summary": "Criar bloqueio",
        "description": "Até 500 bloqueios por organização. Não cancela compromissos que já estão marcados nesse horário. Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inicio": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Começo do bloqueio (com fuso)."
                  },
                  "fim": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Fim do bloqueio (com fuso, até 366 dias depois do início)."
                  },
                  "agenda_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Agenda do bloqueio. Vazio = vale para todas as agendas."
                  },
                  "titulo": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "folga",
                      "almoco",
                      "feriado",
                      "outro"
                    ]
                  },
                  "repetir": {
                    "type": "string",
                    "enum": [
                      "nunca",
                      "diario",
                      "semanal",
                      "anual"
                    ]
                  },
                  "repetir_ate": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Último dia da repetição (AAAA-MM-DD). Só com `repetir` diferente de `nunca`."
                  }
                },
                "required": [
                  "inicio",
                  "fim"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar bloqueio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Bloqueio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/bloqueios/{id}": {
      "get": {
        "operationId": "ver_bloqueio",
        "tags": [
          "Agenda"
        ],
        "summary": "Ver um bloqueio",
        "description": "Escopo: `agenda:ler`.",
        "security": [
          {
            "chave": [
              "agenda:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver um bloqueio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Bloqueio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_bloqueio",
        "tags": [
          "Agenda"
        ],
        "summary": "Atualizar bloqueio",
        "description": "Escopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "inicio": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Começo do bloqueio (com fuso)."
                  },
                  "fim": {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
                    "description": "Fim do bloqueio (com fuso, até 366 dias depois do início)."
                  },
                  "agenda_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Agenda do bloqueio. Vazio = vale para todas as agendas."
                  },
                  "titulo": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "folga",
                      "almoco",
                      "feriado",
                      "outro"
                    ]
                  },
                  "repetir": {
                    "type": "string",
                    "enum": [
                      "nunca",
                      "diario",
                      "semanal",
                      "anual"
                    ]
                  },
                  "repetir_ate": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "date",
                        "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Último dia da repetição (AAAA-MM-DD). Só com `repetir` diferente de `nunca`."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar bloqueio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Bloqueio"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_bloqueio",
        "tags": [
          "Agenda"
        ],
        "summary": "Apagar bloqueio",
        "description": "Apaga um bloqueio (um por chamada). Só o bloqueio: agendas e compromissos não se apagam pela API.\n\nEscopo: `agenda:escrever`.",
        "security": [
          {
            "chave": [
              "agenda:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar bloqueio",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Apagado"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/membros": {
      "get": {
        "operationId": "listar_membros",
        "tags": [
          "Equipe"
        ],
        "summary": "Listar pessoas da equipe",
        "description": "Por ordem de entrada, paginado por cursor. Filtre por papel ou pelo e-mail exato.\n\nEscopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "papel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "dono",
                "gestor",
                "atendente"
              ]
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "schema": {
              "description": "E-mail exato de alguém DESTA organização.",
              "type": "string",
              "maxLength": 254,
              "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
            },
            "description": "E-mail exato de alguém DESTA organização."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar pessoas da equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Membro"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/membros/{id}": {
      "get": {
        "operationId": "ver_membro",
        "tags": [
          "Equipe"
        ],
        "summary": "Ver uma pessoa",
        "description": "O `id` é o id da pessoa (usuário).\n\nEscopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma pessoa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Membro"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_membro",
        "tags": [
          "Equipe"
        ],
        "summary": "Mudar permissões de um atendente",
        "description": "Papel de acesso, WhatsApps visíveis, módulos e agenda. Só os campos enviados mudam. Só vale para atendentes: dono e gestor (e contas de suporte da FORSI) dão 403 `sem_permissao` e só mudam pelo app. O papel (atendente, gestor, dono) nunca muda pela API. Dispara `membro.alterado`.\n\nEscopo: `equipe:permissoes`.",
        "security": [
          {
            "chave": [
              "equipe:permissoes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "papel_de_acesso_id": {
                    "description": "Papel de acesso (Configurações → Equipe → Papéis). Com papel, os módulos e a agenda vêm dele. null tira o papel.",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "caixas": {
                    "description": "WhatsApps que a pessoa vê. Lista vazia = todos.",
                    "maxItems": 200,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                    }
                  },
                  "modulos": {
                    "description": "Módulos liberados. Só sem papel de acesso.",
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "conversas",
                        "contatos",
                        "automacoes",
                        "agentes",
                        "funil",
                        "agenda",
                        "followup",
                        "relatorios"
                      ]
                    }
                  },
                  "agenda": {
                    "description": "Agenda: todas ou só a própria. Só sem papel de acesso.",
                    "type": "string",
                    "enum": [
                      "todas",
                      "propria"
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Mudar permissões de um atendente",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Membro"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "remover_membro",
        "tags": [
          "Equipe"
        ],
        "summary": "Tirar um atendente da equipe",
        "description": "A pessoa perde o acesso na hora e as conversas dela ficam sem responsável. Só vale para atendentes: dono e gestor (e contas de suporte da FORSI) dão 403 `sem_permissao` e só mudam pelo app. Para voltar, convide de novo. Dispara `membro.removido`.\n\nEscopo: `equipe:permissoes`.",
        "security": [
          {
            "chave": [
              "equipe:permissoes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Tirar um atendente da equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoEquipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/presenca": {
      "get": {
        "operationId": "listar_presenca",
        "tags": [
          "Equipe"
        ],
        "summary": "Quem está disponível",
        "description": "Disponível agora = marcou disponível, não está ausente e está dentro do horário de trabalho (no fuso da organização).\n\nEscopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "equipe_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só quem está nesta equipe.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só quem está nesta equipe."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Quem está disponível",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Presenca"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/convites": {
      "get": {
        "operationId": "listar_convites",
        "tags": [
          "Equipe"
        ],
        "summary": "Listar convites abertos",
        "description": "Só os que ainda não foram aceitos nem venceram, do mais novo para o mais antigo. O link do convite nunca aparece aqui.\n\nEscopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar convites abertos",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Convite"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_convite",
        "tags": [
          "Equipe"
        ],
        "summary": "Convidar atendente",
        "description": "Manda o e-mail de convite (como a tela) e responde com o `link` UMA vez. Vale 7 dias. Só atendente. Conta no limite de acessos do plano. Até 20 convites por dia por organização e 3 por e-mail (429 `limite_de_convites`). Repetir com a mesma `Idempotency-Key` devolve o convite sem `link` e sem mandar outro e-mail. Dispara `membro.convidado`.\n\nEscopo: `equipe:permissoes`.",
        "security": [
          {
            "chave": [
              "equipe:permissoes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "maxLength": 254,
                    "pattern": "^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$"
                  },
                  "papel": {
                    "description": "Sempre `atendente` pela API.",
                    "type": "string",
                    "const": "atendente"
                  },
                  "papel_de_acesso_id": {
                    "description": "Papel de acesso aplicado quando a pessoa aceitar.",
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                  },
                  "enviar_email": {
                    "description": "false = não manda o e-mail; use o `link` da resposta. Padrão: manda.",
                    "type": "boolean"
                  }
                },
                "required": [
                  "email"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Convidar atendente",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ConviteComLink"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/convites/{id}": {
      "delete": {
        "operationId": "cancelar_convite",
        "tags": [
          "Equipe"
        ],
        "summary": "Cancelar convite",
        "description": "O link deixa de valer na hora.\n\nEscopo: `equipe:permissoes`.",
        "security": [
          {
            "chave": [
              "equipe:permissoes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Cancelar convite",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoEquipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/convites/{id}/reenviar": {
      "post": {
        "operationId": "reenviar_convite",
        "tags": [
          "Equipe"
        ],
        "summary": "Reenviar convite",
        "description": "Gera um link novo (o antigo para de valer), renova o prazo de 7 dias e manda o e-mail de novo. Conta na mesma cota diária da criação.\n\nEscopo: `equipe:permissoes`.",
        "security": [
          {
            "chave": [
              "equipe:permissoes"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "enviar_email": {
                    "description": "false = só gera o link novo. Padrão: manda o e-mail.",
                    "type": "boolean"
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reenviar convite",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ConviteComLink"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/equipes": {
      "get": {
        "operationId": "listar_equipes",
        "tags": [
          "Equipe"
        ],
        "summary": "Listar equipes (setores)",
        "description": "Cada equipe vem com os ids das pessoas dela.\n\nEscopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar equipes (setores)",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Equipe"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_equipe",
        "tags": [
          "Equipe"
        ],
        "summary": "Criar equipe",
        "description": "Nome único na organização (409 `equipe_repetida`). Mande `Idempotency-Key` para poder repetir com segurança.\n\nEscopo: `equipe:escrever`.",
        "security": [
          {
            "chave": [
              "equipe:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "distribuicao": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "rodizio",
                      "menos_ocupado"
                    ],
                    "description": "Como as conversas novas da equipe são distribuídas: manual, rodízio ou para quem tem menos conversas abertas."
                  }
                },
                "required": [
                  "nome"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Equipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/equipes/{id}": {
      "get": {
        "operationId": "ver_equipe",
        "tags": [
          "Equipe"
        ],
        "summary": "Ver uma equipe",
        "description": "Escopo: `equipe:ler`.",
        "security": [
          {
            "chave": [
              "equipe:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Equipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "atualizar_equipe",
        "tags": [
          "Equipe"
        ],
        "summary": "Atualizar equipe",
        "description": "Nome, cor e distribuição. Só os campos enviados mudam.\n\nEscopo: `equipe:escrever`.",
        "security": [
          {
            "chave": [
              "equipe:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 40
                  },
                  "cor": {
                    "type": "string",
                    "enum": [
                      "slate",
                      "blue",
                      "violet",
                      "amber",
                      "emerald",
                      "green",
                      "rose",
                      "cyan",
                      "orange"
                    ]
                  },
                  "distribuicao": {
                    "type": "string",
                    "enum": [
                      "manual",
                      "rodizio",
                      "menos_ocupado"
                    ],
                    "description": "Como as conversas novas da equipe são distribuídas: manual, rodízio ou para quem tem menos conversas abertas."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atualizar equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Equipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_equipe",
        "tags": [
          "Equipe"
        ],
        "summary": "Apagar equipe",
        "description": "As pessoas continuam na organização; as conversas da equipe ficam sem equipe.\n\nEscopo: `equipe:escrever`.",
        "security": [
          {
            "chave": [
              "equipe:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoEquipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/equipe/equipes/{id}/membros": {
      "patch": {
        "operationId": "atualizar_membros_equipe",
        "tags": [
          "Equipe"
        ],
        "summary": "Pôr e tirar pessoas da equipe",
        "description": "Até 50 em cada lista. Qualquer pessoa da organização pode estar numa equipe: isso não muda o que ela pode ver.\n\nEscopo: `equipe:escrever`.",
        "security": [
          {
            "chave": [
              "equipe:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "adicionar": {
                    "description": "Ids de pessoas (GET /equipe/membros) para pôr na equipe.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                    }
                  },
                  "remover": {
                    "description": "Ids de pessoas para tirar da equipe.",
                    "maxItems": 50,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                    }
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Pôr e tirar pessoas da equipe",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Equipe"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/conversas/{id}/atribuir": {
      "post": {
        "operationId": "atribuir_conversa",
        "tags": [
          "Equipe"
        ],
        "summary": "Atribuir ou transferir conversa",
        "description": "Muda o responsável e/ou a equipe; null tira. Mesmo efeito da tela: registra no histórico da conversa (\"Integração “nome da chave” passou para...\"), avisa a pessoa, pausa o agente de IA da conversa e dispara `conversa.atribuida`.\n\nEscopo: `equipe:escrever`.",
        "security": [
          {
            "chave": [
              "equipe:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "responsavel_id": {
                    "description": "Pessoa responsável (GET /equipe/membros). null tira o responsável.",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "equipe_id": {
                    "description": "Equipe da conversa (GET /equipe/equipes). null tira a equipe.",
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Atribuir ou transferir conversa",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/Conversa"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/instagram/contas": {
      "get": {
        "operationId": "listar_contas_instagram",
        "tags": [
          "Automações"
        ],
        "summary": "Listar contas do Instagram",
        "description": "Contas conectadas por login do Instagram, as que aceitam regras de comentário. O `id` é o `conexao_id` das regras.\n\nEscopo: `automacoes:ler`.",
        "security": [
          {
            "chave": [
              "automacoes:ler"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Listar contas do Instagram",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ContaInstagram"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/automacoes": {
      "get": {
        "operationId": "listar_automacoes_de_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Listar automações para ligar a uma regra",
        "description": "Com `gatilho=comentario`: as automações que uma regra de comentário pode iniciar (`automacao_id`).\n\nEscopo: `automacoes:ler`.",
        "security": [
          {
            "chave": [
              "automacoes:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "gatilho",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "const": "comentario",
              "description": "Por enquanto só `comentario`: automações que podem ser ligadas a uma regra de comentário."
            },
            "description": "Por enquanto só `comentario`: automações que podem ser ligadas a uma regra de comentário."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar automações para ligar a uma regra",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/AutomacaoResumo"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/regras-comentario": {
      "get": {
        "operationId": "listar_regras_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Listar regras de comentário",
        "description": "Regras que respondem comentários do Instagram, paginado por cursor. Filtre por conta, publicação, estado ou `tipo` (`comum` ou `seguir`). Regras `seguir` trazem o bloco `seguir` completo e `estatisticas`.\n\nEscopo: `automacoes:ler`.",
        "security": [
          {
            "chave": [
              "automacoes:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "conexao_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só as regras desta conta do Instagram.",
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
            },
            "description": "Só as regras desta conta do Instagram."
          },
          {
            "name": "post_id",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só as regras desta publicação.",
              "type": "string",
              "pattern": "^[0-9A-Za-z_]{1,60}$"
            },
            "description": "Só as regras desta publicação."
          },
          {
            "name": "ativo",
            "in": "query",
            "required": false,
            "schema": {
              "description": "true ou false.",
              "type": "string",
              "enum": [
                "true",
                "false"
              ]
            },
            "description": "true ou false."
          },
          {
            "name": "tipo",
            "in": "query",
            "required": false,
            "schema": {
              "description": "Só as regras deste tipo: `comum` ou `seguir`.",
              "type": "string",
              "enum": [
                "comum",
                "seguir"
              ]
            },
            "description": "Só as regras deste tipo: `comum` ou `seguir`."
          },
          {
            "name": "limite",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "description": "Itens por página (1 a 100, padrão 50)."
            },
            "description": "Itens por página (1 a 100, padrão 50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 80,
              "pattern": "^\\d{1,20}_[0-9a-f-]{36}$",
              "description": "O valor de `proximo` da página anterior."
            },
            "description": "O valor de `proximo` da página anterior."
          }
        ],
        "responses": {
          "200": {
            "description": "Listar regras de comentário",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/RegraComentario"
                      }
                    },
                    "proximo": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Cursor da próxima página; null quando acabou. Mande em ?cursor=."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "criar_regra_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Criar regra de comentário",
        "description": "Nasce desligada, a menos que mande `ativo: true`. Informe `post_id`: sem ele a regra vale para todas as publicações. A primeira regra que combinar com o comentário vale. Até 200 regras por organização (422 `limite_de_regras`). Com `tipo: \"seguir\"` (\"Seguir para receber\") a pessoa precisa seguir a conta para receber o conteúdo: mande `resposta_privada` e `seguir.conteudo.texto`; o resto de `seguir` tem padrão (422 `seguir_invalido` se algum campo passar do limite). Sem `tipo`, a regra é `comum`. `qualquer_comentario`, `botoes` (inclusive botões de link) e `tipo: \"seguir\"` dão 403 `recurso_desligado` se não estiverem liberados. Mande `Idempotency-Key` para repetir com segurança.\n\nEscopo: `automacoes:escrever`.",
        "security": [
          {
            "chave": [
              "automacoes:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "Nome da regra, só para você identificar."
                  },
                  "conexao_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
                    "description": "Conta do Instagram (GET /instagram/contas)."
                  },
                  "post_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^[0-9A-Za-z_]{1,60}$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Id da publicação. null = vale para qualquer publicação (não recomendado: responde em todos os posts)."
                  },
                  "palavras": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "description": "Até 30 palavras. Vazio só com `qualquer_comentario: true`."
                  },
                  "modo": {
                    "type": "string",
                    "enum": [
                      "contem",
                      "igual"
                    ],
                    "description": "`contem`: o comentário tem a palavra. `igual`: o comentário é só a palavra."
                  },
                  "qualquer_comentario": {
                    "type": "boolean",
                    "description": "true = dispara em qualquer comentário, sem palavras. Precisa estar liberado na organização."
                  },
                  "responder_publico": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 2200
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Resposta pública ao comentário (até 2200 caracteres)."
                  },
                  "respostas_publicas": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2200
                    },
                    "description": "Variações da resposta pública (até 5), sorteadas a cada comentário. Precisa de `responder_publico`."
                  },
                  "ocultar_apos": {
                    "type": "boolean",
                    "description": "Oculta o comentário depois de responder. Precisa de `responder_publico`."
                  },
                  "resposta_privada": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Mensagem direta enviada a quem comentou (até 1000 caracteres)."
                  },
                  "automacao_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Automação a iniciar com a resposta privada (GET /automacoes?gatilho=comentario). Precisa de `resposta_privada`."
                  },
                  "botoes": {
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 20
                        },
                        {
                          "type": "object",
                          "properties": {
                            "titulo": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 20,
                              "description": "Texto do botão (até 20 caracteres)."
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 2000,
                              "description": "Link `https://` (até 2000 caracteres). Com `url` o botão abre o link; sem `url` ele devolve o toque (postback)."
                            }
                          },
                          "required": [
                            "titulo"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    },
                    "description": "Até 3 botões na mensagem direta. Cada botão é um texto (devolve o toque) ou `{ titulo, url? }`; com `url` (https) abre o link. Se a Meta recusar os botões nessa resposta, a mensagem sai só com texto e os links entram no fim do texto. Precisa de `resposta_privada` e de estar liberado na organização."
                  },
                  "ativo": {
                    "type": "boolean",
                    "description": "Liga ou desliga a regra. Ao criar, o padrão é false."
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "comum",
                      "seguir"
                    ],
                    "description": "`comum` (padrão): responde e manda a mensagem. `seguir`: o conteúdo só é entregue a quem segue a conta; veja `seguir`. No tipo `seguir` não use `automacao_id` nem `botoes`."
                  },
                  "seguir": {
                    "type": "object",
                    "properties": {
                      "botao_receber": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20,
                        "description": "Texto do botão que vai junto da mensagem do comentário. 1 a 20 caracteres, sem variáveis (o banco recusa \"{\"). Padrão: \"Quero receber\"."
                      },
                      "texto_nao_segue": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 640,
                        "description": "Mensagem para quem pediu e ainda não segue a conta. 1 a 640 caracteres. Padrão: \"Para receber, é só seguir o perfil @{conta} e depois tocar em \"Estou seguindo\".\". Aceita {nome}, {usuario} e {conta}."
                      },
                      "botao_estou_seguindo": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20,
                        "description": "Texto do botão para avisar que passou a seguir. 1 a 20 caracteres, sem variáveis (o banco recusa \"{\"). Padrão: \"Estou seguindo\"."
                      },
                      "texto_ainda_nao_segue": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 640,
                        "description": "Mensagem quando a pessoa toca em \"Estou seguindo\" e ainda não segue. 1 a 640 caracteres. Padrão: \"Ainda não apareceu que você segue @{conta}. Siga o perfil e toque de novo em \"Estou seguindo\".\". Aceita {nome}, {usuario} e {conta}."
                      },
                      "texto_ja_segue": {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 640,
                        "description": "Mensagem antes do conteúdo para quem já seguia. 0 a 640 caracteres. Padrão: \"Que bom ter você por aqui! Aqui está o que você pediu:\". Vazio (\"\") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}."
                      },
                      "texto_seguiu_depois": {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 640,
                        "description": "Mensagem antes do conteúdo para quem acabou de seguir. 0 a 640 caracteres. Padrão: \"Obrigado por seguir! Aqui está o que você pediu:\". Vazio (\"\") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}."
                      },
                      "conteudo": {
                        "type": "object",
                        "properties": {
                          "texto": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 640,
                            "description": "O que a pessoa recebe (obrigatório). 1 a 640 caracteres. Aceita {nome}, {usuario} e {conta}."
                          },
                          "botao": {
                            "description": "Botão de link junto do conteúdo. Padrão: null (sem botão).",
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "titulo": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 20,
                                    "description": "Texto do botão (1 a 20 caracteres)."
                                  },
                                  "url": {
                                    "type": "string",
                                    "maxLength": 2000,
                                    "description": "Link `https://` que o botão abre (até 2000 caracteres)."
                                  }
                                },
                                "required": [
                                  "titulo",
                                  "url"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "texto"
                        ],
                        "additionalProperties": false,
                        "description": "O que é entregue quando a pessoa segue: texto e, se quiser, um botão de link. Obrigatório para o tipo `seguir`."
                      },
                      "max_tentativas": {
                        "description": "Quantas vezes conferir se a pessoa passou a seguir (1 a 50). Padrão: null = confere até seguir, no máximo 50 vezes.",
                        "anyOf": [
                          {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 50
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "texto_limite": {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 640,
                            "description": "Mensagem enviada uma vez quando `max_tentativas` acaba; depois a regra para de responder. 1 a 640 caracteres. Aceita {nome}, {usuario} e {conta}."
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "se_nao_verificar": {
                        "description": "Se a Meta não deixar conferir: `enviar` (padrão) entrega o conteúdo assim mesmo; `pedir_de_novo` pede para seguir outra vez.",
                        "type": "string",
                        "enum": [
                          "enviar",
                          "pedir_de_novo"
                        ]
                      }
                    },
                    "required": [
                      "conteudo"
                    ],
                    "additionalProperties": false,
                    "description": "Configuração do tipo `seguir`. Campos omitidos usam o padrão. Só `conteudo.texto` é obrigatório. Precisa de `resposta_privada` (até 640 caracteres) e estar liberado na organização (403 `recurso_desligado`)."
                  }
                },
                "required": [
                  "nome",
                  "conexao_id"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Criar regra de comentário",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RegraComentario"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    },
    "/regras-comentario/{id}": {
      "get": {
        "operationId": "ver_regra_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Ver uma regra de comentário",
        "description": "Escopo: `automacoes:ler`.",
        "security": [
          {
            "chave": [
              "automacoes:ler"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Ver uma regra de comentário",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RegraComentario"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "patch": {
        "operationId": "editar_regra_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Editar regra de comentário",
        "description": "Só os campos enviados mudam. `ativo` liga ou desliga. Mudar `tipo` para `comum` apaga o bloco `seguir`. Em `seguir`, só os campos enviados mudam e os omitidos mantêm o valor atual (dentro de `conteudo` também; `conteudo.botao: null` tira o botão). O resultado final tem de continuar válido (por exemplo, não dá para ficar sem resposta nenhuma).\n\nEscopo: `automacoes:escrever`.",
        "security": [
          {
            "chave": [
              "automacoes:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Repetir o mesmo pedido com a mesma chave (24 h) devolve a mesma resposta sem enviar de novo; resposta repetida vem com Idempotent-Replayed: true. Chaves configuradas para exigir idempotência recebem 400 idempotencia_obrigatoria quando o cabeçalho falta."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "nome": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 80,
                    "description": "Nome da regra, só para você identificar."
                  },
                  "conexao_id": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$",
                    "description": "Conta do Instagram (GET /instagram/contas)."
                  },
                  "post_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "pattern": "^[0-9A-Za-z_]{1,60}$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Id da publicação. null = vale para qualquer publicação (não recomendado: responde em todos os posts)."
                  },
                  "palavras": {
                    "maxItems": 30,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "description": "Até 30 palavras. Vazio só com `qualquer_comentario: true`."
                  },
                  "modo": {
                    "type": "string",
                    "enum": [
                      "contem",
                      "igual"
                    ],
                    "description": "`contem`: o comentário tem a palavra. `igual`: o comentário é só a palavra."
                  },
                  "qualquer_comentario": {
                    "type": "boolean",
                    "description": "true = dispara em qualquer comentário, sem palavras. Precisa estar liberado na organização."
                  },
                  "responder_publico": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 2200
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Resposta pública ao comentário (até 2200 caracteres)."
                  },
                  "respostas_publicas": {
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2200
                    },
                    "description": "Variações da resposta pública (até 5), sorteadas a cada comentário. Precisa de `responder_publico`."
                  },
                  "ocultar_apos": {
                    "type": "boolean",
                    "description": "Oculta o comentário depois de responder. Precisa de `responder_publico`."
                  },
                  "resposta_privada": {
                    "anyOf": [
                      {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 1000
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Mensagem direta enviada a quem comentou (até 1000 caracteres)."
                  },
                  "automacao_id": {
                    "anyOf": [
                      {
                        "type": "string",
                        "format": "uuid",
                        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$"
                      },
                      {
                        "type": "null"
                      }
                    ],
                    "description": "Automação a iniciar com a resposta privada (GET /automacoes?gatilho=comentario). Precisa de `resposta_privada`."
                  },
                  "botoes": {
                    "maxItems": 3,
                    "type": "array",
                    "items": {
                      "anyOf": [
                        {
                          "type": "string",
                          "minLength": 1,
                          "maxLength": 20
                        },
                        {
                          "type": "object",
                          "properties": {
                            "titulo": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 20,
                              "description": "Texto do botão (até 20 caracteres)."
                            },
                            "url": {
                              "type": "string",
                              "maxLength": 2000,
                              "description": "Link `https://` (até 2000 caracteres). Com `url` o botão abre o link; sem `url` ele devolve o toque (postback)."
                            }
                          },
                          "required": [
                            "titulo"
                          ],
                          "additionalProperties": false
                        }
                      ]
                    },
                    "description": "Até 3 botões na mensagem direta. Cada botão é um texto (devolve o toque) ou `{ titulo, url? }`; com `url` (https) abre o link. Se a Meta recusar os botões nessa resposta, a mensagem sai só com texto e os links entram no fim do texto. Precisa de `resposta_privada` e de estar liberado na organização."
                  },
                  "ativo": {
                    "type": "boolean",
                    "description": "Liga ou desliga a regra. Ao criar, o padrão é false."
                  },
                  "tipo": {
                    "type": "string",
                    "enum": [
                      "comum",
                      "seguir"
                    ],
                    "description": "`comum` (padrão): responde e manda a mensagem. `seguir`: o conteúdo só é entregue a quem segue a conta; veja `seguir`. No tipo `seguir` não use `automacao_id` nem `botoes`."
                  },
                  "seguir": {
                    "type": "object",
                    "properties": {
                      "botao_receber": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20,
                        "description": "Texto do botão que vai junto da mensagem do comentário. 1 a 20 caracteres, sem variáveis (o banco recusa \"{\"). Padrão: \"Quero receber\"."
                      },
                      "texto_nao_segue": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 640,
                        "description": "Mensagem para quem pediu e ainda não segue a conta. 1 a 640 caracteres. Padrão: \"Para receber, é só seguir o perfil @{conta} e depois tocar em \"Estou seguindo\".\". Aceita {nome}, {usuario} e {conta}."
                      },
                      "botao_estou_seguindo": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 20,
                        "description": "Texto do botão para avisar que passou a seguir. 1 a 20 caracteres, sem variáveis (o banco recusa \"{\"). Padrão: \"Estou seguindo\"."
                      },
                      "texto_ainda_nao_segue": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 640,
                        "description": "Mensagem quando a pessoa toca em \"Estou seguindo\" e ainda não segue. 1 a 640 caracteres. Padrão: \"Ainda não apareceu que você segue @{conta}. Siga o perfil e toque de novo em \"Estou seguindo\".\". Aceita {nome}, {usuario} e {conta}."
                      },
                      "texto_ja_segue": {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 640,
                        "description": "Mensagem antes do conteúdo para quem já seguia. 0 a 640 caracteres. Padrão: \"Que bom ter você por aqui! Aqui está o que você pediu:\". Vazio (\"\") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}."
                      },
                      "texto_seguiu_depois": {
                        "type": "string",
                        "minLength": 0,
                        "maxLength": 640,
                        "description": "Mensagem antes do conteúdo para quem acabou de seguir. 0 a 640 caracteres. Padrão: \"Obrigado por seguir! Aqui está o que você pediu:\". Vazio (\"\") = não envia este texto, só o conteúdo. Aceita {nome}, {usuario} e {conta}."
                      },
                      "conteudo": {
                        "description": "Só o que mudar: `texto`, `botao` ou os dois. `botao: null` tira o botão.",
                        "type": "object",
                        "properties": {
                          "texto": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 640,
                            "description": "O que a pessoa recebe (obrigatório). 1 a 640 caracteres. Aceita {nome}, {usuario} e {conta}."
                          },
                          "botao": {
                            "description": "Botão de link junto do conteúdo. Padrão: null (sem botão).",
                            "anyOf": [
                              {
                                "type": "object",
                                "properties": {
                                  "titulo": {
                                    "type": "string",
                                    "minLength": 1,
                                    "maxLength": 20,
                                    "description": "Texto do botão (1 a 20 caracteres)."
                                  },
                                  "url": {
                                    "type": "string",
                                    "maxLength": 2000,
                                    "description": "Link `https://` que o botão abre (até 2000 caracteres)."
                                  }
                                },
                                "required": [
                                  "titulo",
                                  "url"
                                ],
                                "additionalProperties": false
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "additionalProperties": false
                      },
                      "max_tentativas": {
                        "description": "Quantas vezes conferir se a pessoa passou a seguir (1 a 50). Padrão: null = confere até seguir, no máximo 50 vezes.",
                        "anyOf": [
                          {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 50
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "texto_limite": {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 640,
                            "description": "Mensagem enviada uma vez quando `max_tentativas` acaba; depois a regra para de responder. 1 a 640 caracteres. Aceita {nome}, {usuario} e {conta}."
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "se_nao_verificar": {
                        "description": "Se a Meta não deixar conferir: `enviar` (padrão) entrega o conteúdo assim mesmo; `pedir_de_novo` pede para seguir outra vez.",
                        "type": "string",
                        "enum": [
                          "enviar",
                          "pedir_de_novo"
                        ]
                      }
                    },
                    "additionalProperties": false,
                    "description": "Mesmo formato de `seguir`, com todos os campos opcionais (inclusive dentro de `conteudo`). Só os campos enviados mudam; os omitidos mantêm o valor atual. `max_tentativas: null` e `texto_limite: null` voltam ao padrão (sem limite). Se a regra era `comum`, o que faltar vem dos padrões e `conteudo.texto` é obrigatório."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Editar regra de comentário",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/RegraComentario"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "apagar_regra_comentario",
        "tags": [
          "Automações"
        ],
        "summary": "Apagar regra de comentário",
        "description": "Sem volta. Para só pausar, use PATCH com `ativo: false`.\n\nEscopo: `automacoes:escrever`.",
        "security": [
          {
            "chave": [
              "automacoes:escrever"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Apagar regra de comentário",
            "headers": {
              "X-RateLimit-Limit": {
                "description": "Requisições permitidas na janela de 1 minuto.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Remaining": {
                "description": "Quantas ainda cabem na janela.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-RateLimit-Reset": {
                "description": "Segundos até a janela reiniciar.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id desta requisição (mande ao suporte).",
                "schema": {
                  "type": "string",
                  "format": "uuid"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "dados"
                  ],
                  "properties": {
                    "dados": {
                      "$ref": "#/components/schemas/ApagadoRegra"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Chave ausente ou inválida (resposta igual para qualquer motivo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "403": {
            "description": "Plano sem API, escopo insuficiente ou https/origem recusados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "404": {
            "description": "Não existe nesta organização.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "409": {
            "description": "Conflito (repetido, Idempotency-Key com outro corpo).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            }
          },
          "422": {
            "description": "Dados inválidos ou regra de negócio (ex.: janela_fechada; conta_restrita = a Meta restringiu a conta por spam: erro traz os campos de RestricaoMeta, como ate, escopo, motivo e retry_after_s).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Só em conta_restrita: segundos até a restrição acabar (= erro.retry_after_s).",
                "schema": {
                  "type": "integer"
                }
              }
            }
          },
          "429": {
            "description": "Limite de requisições. Veja Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Erro"
                }
              }
            },
            "headers": {
              "Retry-After": {
                "description": "Segundos para tentar de novo.",
                "schema": {
                  "type": "integer"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {
    "mensagem.recebida": {
      "post": {
        "summary": "mensagem.recebida",
        "description": "O contato mandou uma mensagem.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "mensagem.enviada": {
      "post": {
        "summary": "mensagem.enviada",
        "description": "Uma mensagem sua saiu (pela tela, por um agente ou pela API).\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "mensagem.status": {
      "post": {
        "summary": "mensagem.status",
        "description": "Mudou o status de uma mensagem enviada: entregue, lida, falhou...\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "conversa.criada": {
      "post": {
        "summary": "conversa.criada",
        "description": "Nasceu uma conversa nova.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "conversa.atribuida": {
      "post": {
        "summary": "conversa.atribuida",
        "description": "A conversa mudou de responsável ou de equipe.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "conversa.encerrada": {
      "post": {
        "summary": "conversa.encerrada",
        "description": "A conversa foi resolvida.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "contato.criado": {
      "post": {
        "summary": "contato.criado",
        "description": "Um contato novo foi criado.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "negocio.criado": {
      "post": {
        "summary": "negocio.criado",
        "description": "Um negócio novo entrou no funil.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "negocio.movido": {
      "post": {
        "summary": "negocio.movido",
        "description": "Um negócio mudou de etapa.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "negocio.ganho": {
      "post": {
        "summary": "negocio.ganho",
        "description": "Um negócio foi marcado como ganho.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "negocio.perdido": {
      "post": {
        "summary": "negocio.perdido",
        "description": "Um negócio foi marcado como perdido.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "agendamento.criado": {
      "post": {
        "summary": "agendamento.criado",
        "description": "Um compromisso foi marcado (pela tela, pelo agente ou pela API).\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "agendamento.remarcado": {
      "post": {
        "summary": "agendamento.remarcado",
        "description": "Um compromisso mudou de dia, hora ou agenda. Vem com o horário anterior.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "agendamento.cancelado": {
      "post": {
        "summary": "agendamento.cancelado",
        "description": "Um compromisso foi cancelado.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "agendamento.confirmado": {
      "post": {
        "summary": "agendamento.confirmado",
        "description": "Um compromisso foi confirmado.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "membro.convidado": {
      "post": {
        "summary": "membro.convidado",
        "description": "Alguém foi convidado para a equipe (pela tela ou pela API).\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "membro.entrou": {
      "post": {
        "summary": "membro.entrou",
        "description": "Uma pessoa aceitou o convite e entrou na equipe.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "membro.alterado": {
      "post": {
        "summary": "membro.alterado",
        "description": "Mudou o papel ou as permissões de alguém. Vem com o valor anterior.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    },
    "membro.removido": {
      "post": {
        "summary": "membro.removido",
        "description": "Uma pessoa saiu da equipe.\n\nConfira X-Forsi-Signature antes de confiar no corpo. Responda 2xx em até 10 s; outra resposta conta como falha e volta a tentar.",
        "parameters": [
          {
            "name": "X-Forsi-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Forsi-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Id da entrega (muda no reenvio)."
          },
          {
            "name": "X-Forsi-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "description": "Segundos Unix do envio."
          },
          {
            "name": "X-Forsi-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`t=<timestamp>,v1=<hex>`: HMAC-SHA256 com o segredo sobre `<timestamp>.<corpo cru>`. Durante a troca de segredo vêm dois v1."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Evento"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recebido."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "chave": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "fcv2_live_<id>_<segredo>",
        "description": "Escopos: `mensagens:enviar` (Enviar mensagens (texto, mídia e modelos)); `mensagens:ler` (Ler mensagens das conversas); `contatos:ler` (Ler e buscar contatos); `contatos:escrever` (Criar, editar e apagar contatos); `conversas:ler` (Listar e ler conversas); `modelos:ler` (Listar modelos aprovados do WhatsApp); `webhooks:gerir` (Cadastrar e gerir webhooks); `funil:ler` (Ler funis, etapas, negócios e notas); `funil:escrever` (Criar e editar funis, etapas e negócios; mover, ganhar, perder e anotar); `funil:apagar` (Apagar negócios, notas, etapas e funis (sem volta)); `relatorios:ler` (Ler relatórios: volume, tempo de resposta, equipe, caixas, agente de IA e créditos usados); `agenda:ler` (Ler agendas, horários livres, compromissos e bloqueios); `agenda:escrever` (Criar e editar agendas e bloqueios; marcar, remarcar, confirmar, cancelar e dar presença em compromissos (não apaga nada)); `equipe:ler` (Ler pessoas da equipe, presença, convites abertos e equipes (setores)); `equipe:escrever` (Criar, editar e apagar equipes (setores), pôr e tirar pessoas delas e atribuir conversas); `equipe:permissoes` (Convidar atendentes, reenviar e cancelar convites, mudar permissões e remover atendentes (nunca mexe em dono ou gestor)); `automacoes:ler` (Ler regras de comentário do Instagram, contas conectadas e automações); `automacoes:escrever` (Criar, editar, ligar, desligar e apagar regras de comentário do Instagram)."
      }
    },
    "schemas": {
      "RelatorioVolume": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "conversas_novas": {
                "type": "integer"
              },
              "conversas_resolvidas": {
                "type": "integer"
              },
              "mensagens_recebidas": {
                "type": "integer"
              },
              "mensagens_enviadas": {
                "type": "integer"
              },
              "mensagens_do_agente": {
                "type": "integer",
                "description": "Das enviadas, as que o agente de IA mandou."
              },
              "notas_internas": {
                "type": "integer"
              }
            }
          },
          "por_hora": {
            "type": "array",
            "description": "24 itens, hora do dia no fuso da organização.",
            "items": {
              "type": "object",
              "properties": {
                "hora": {
                  "type": "integer"
                },
                "mensagens_recebidas": {
                  "type": "integer"
                },
                "mensagens_enviadas": {
                  "type": "integer"
                }
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por dia, semana ou mês.",
            "items": {
              "type": "object",
              "properties": {
                "inicio": {
                  "type": "string",
                  "format": "date"
                },
                "fim": {
                  "type": "string",
                  "format": "date",
                  "description": "Último dia da linha (nas pontas do período, a linha é cortada)."
                },
                "conversas_novas": {
                  "type": "integer"
                },
                "conversas_resolvidas": {
                  "type": "integer"
                },
                "mensagens_recebidas": {
                  "type": "integer"
                },
                "mensagens_enviadas": {
                  "type": "integer"
                },
                "mensagens_do_agente": {
                  "type": "integer"
                },
                "notas_internas": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "RelatorioTempo": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "primeiras_respostas": {
                "type": "integer"
              },
              "sem_resposta": {
                "type": "integer"
              },
              "mediana_primeira_resposta_s": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Mediana da primeira resposta (segundos)"
              },
              "p90_primeira_resposta_s": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "90% das conversas foram respondidas em até (segundos)"
              },
              "respondidas_em_ate_1_min_pct": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "respondidas_em_ate_5_min_pct": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "respondidas_em_ate_15_min_pct": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "respondidas_em_ate_1_h_pct": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Porcentagem (0 a 100) das conversas com primeira resposta em até 1 hora."
              },
              "resolvidas": {
                "type": "integer"
              },
              "mediana_resolucao_s": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Mediana até resolver (segundos)"
              },
              "p90_resolucao_s": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "90% das conversas foram resolvidas em até (segundos)"
              }
            }
          },
          "faixas_primeira_resposta": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "faixa": {
                  "type": "string",
                  "example": "1 a 5 min"
                },
                "quantidade": {
                  "type": "integer"
                }
              }
            }
          },
          "faixas_resolucao": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "faixa": {
                  "type": "string",
                  "example": "1 a 5 min"
                },
                "quantidade": {
                  "type": "integer"
                }
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por dia, semana ou mês.",
            "items": {
              "type": "object",
              "properties": {
                "inicio": {
                  "type": "string",
                  "format": "date"
                },
                "fim": {
                  "type": "string",
                  "format": "date",
                  "description": "Último dia da linha (nas pontas do período, a linha é cortada)."
                },
                "primeiras_respostas": {
                  "type": "integer"
                },
                "mediana_primeira_resposta_s": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Mediana da primeira resposta (segundos)"
                },
                "resolvidas": {
                  "type": "integer"
                },
                "mediana_resolucao_s": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Mediana até resolver (segundos)"
                }
              }
            }
          }
        }
      },
      "RelatorioAtendentes": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "atendentes": {
                "type": "integer"
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por pessoa da equipe.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "nome": {
                  "type": "string"
                },
                "papel": {
                  "type": "string"
                },
                "conversas_atendidas": {
                  "type": "integer"
                },
                "mensagens_enviadas": {
                  "type": "integer"
                },
                "conversas_resolvidas": {
                  "type": "integer"
                },
                "abertas_agora": {
                  "type": "integer"
                },
                "primeiras_respostas": {
                  "type": "integer"
                },
                "mediana_primeira_resposta_s": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "description": "Mediana da primeira resposta (segundos)"
                }
              }
            }
          }
        }
      },
      "RelatorioCaixas": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "caixas": {
                "type": "integer"
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por caixa.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "nome": {
                  "type": "string"
                },
                "canal": {
                  "type": "string"
                },
                "telefone": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "conversas_novas": {
                  "type": "integer"
                },
                "conversas_resolvidas": {
                  "type": "integer"
                },
                "conversas_com_mensagens": {
                  "type": "integer"
                },
                "mensagens_recebidas": {
                  "type": "integer"
                },
                "mensagens_enviadas": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "RelatorioAgenteDeIa": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "conversas": {
                "type": "integer"
              },
              "sem_agente": {
                "type": "integer"
              },
              "com_agente": {
                "type": "integer"
              },
              "passadas_para_a_equipe": {
                "type": "integer"
              },
              "resolvidas_pelo_agente": {
                "type": "integer"
              },
              "em_andamento": {
                "type": "integer"
              },
              "taxa_resolucao": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Resolvidas pelo agente / conversas com agente (0 a 1)."
              }
            }
          },
          "motivos_da_passagem": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "motivo": {
                  "type": "string"
                },
                "quantidade": {
                  "type": "integer"
                }
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por agente de IA.",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "nome": {
                  "type": "string"
                },
                "conversas_com_agente": {
                  "type": "integer"
                },
                "passadas_para_a_equipe": {
                  "type": "integer"
                },
                "resolvidas_pelo_agente": {
                  "type": "integer"
                },
                "em_andamento": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "RelatorioCreditos": {
        "type": "object",
        "properties": {
          "periodo": {
            "type": "object",
            "description": "O período que valeu na consulta (com os padrões aplicados).",
            "properties": {
              "de": {
                "type": "string",
                "format": "date"
              },
              "ate": {
                "type": "string",
                "format": "date"
              },
              "dias": {
                "type": "integer"
              },
              "fuso": {
                "type": "string",
                "example": "America/Sao_Paulo"
              },
              "granularidade": {
                "type": "string",
                "enum": [
                  "dia",
                  "semana",
                  "mes"
                ],
                "description": "Só nos relatórios em série."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "resumo": {
            "type": "object",
            "properties": {
              "creditos_usados": {
                "type": "integer",
                "description": "Créditos gastos no período."
              },
              "creditos_disponiveis": {
                "type": "integer"
              },
              "creditos_do_plano": {
                "type": "integer"
              },
              "creditos_extras": {
                "type": "integer"
              },
              "renovam_em": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "por_motivo": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "motivo": {
                  "type": "string",
                  "example": "resposta do agente"
                },
                "creditos_usados": {
                  "type": "integer"
                },
                "vezes": {
                  "type": "integer"
                }
              }
            }
          },
          "linhas": {
            "type": "array",
            "description": "Uma linha por dia, semana ou mês.",
            "items": {
              "type": "object",
              "properties": {
                "inicio": {
                  "type": "string",
                  "format": "date"
                },
                "fim": {
                  "type": "string",
                  "format": "date",
                  "description": "Último dia da linha (nas pontas do período, a linha é cortada)."
                },
                "creditos_usados": {
                  "type": "integer"
                }
              }
            }
          }
        }
      },
      "Agenda": {
        "type": "object",
        "description": "Uma agenda (profissional ou sala). Campos sem valor não aparecem.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "cor": {
            "type": "string"
          },
          "fuso": {
            "type": "string",
            "example": "America/Sao_Paulo"
          },
          "ativa": {
            "type": "boolean"
          },
          "duracao_min": {
            "type": "integer"
          },
          "intervalo_min": {
            "type": "integer"
          },
          "antecedencia_min": {
            "type": "integer"
          },
          "horario": {
            "type": "object",
            "description": "Dia da semana (0 domingo a 6 sábado) para faixas [início, fim].",
            "additionalProperties": {
              "type": "array"
            }
          },
          "lembretes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "antes_min": {
                  "type": "integer"
                }
              }
            }
          },
          "mensagem_lembrete": {
            "type": "string"
          },
          "profissional": {
            "type": "object",
            "description": "Quando a agenda é de uma pessoa da equipe.",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": "string"
              }
            }
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Slot": {
        "type": "object",
        "description": "Um horário livre.",
        "properties": {
          "agenda_id": {
            "type": "string",
            "format": "uuid"
          },
          "agenda": {
            "type": "string"
          },
          "cor": {
            "type": "string"
          },
          "inicio": {
            "type": "string",
            "format": "date-time"
          },
          "fim": {
            "type": "string",
            "format": "date-time"
          },
          "fuso": {
            "type": "string"
          },
          "inicio_local": {
            "type": "string",
            "description": "Começo no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          },
          "fim_local": {
            "type": "string",
            "description": "Fim no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          }
        }
      },
      "Disponibilidade": {
        "type": "object",
        "properties": {
          "fuso": {
            "type": "string"
          },
          "duracao_min": {
            "type": "integer"
          },
          "slots": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Slot"
            }
          },
          "truncado": {
            "type": "boolean",
            "description": "Verdadeiro quando passou de 400 horários: estreite a janela."
          }
        }
      },
      "Compromisso": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agenda_id": {
            "type": "string",
            "format": "uuid"
          },
          "agenda": {
            "type": "string"
          },
          "cor": {
            "type": "string"
          },
          "titulo": {
            "type": "string"
          },
          "inicio": {
            "type": "string",
            "format": "date-time"
          },
          "fim": {
            "type": "string",
            "format": "date-time"
          },
          "fuso": {
            "type": "string"
          },
          "inicio_local": {
            "type": "string",
            "description": "Começo no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          },
          "fim_local": {
            "type": "string",
            "description": "Fim no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          },
          "duracao_min": {
            "type": "integer"
          },
          "estado": {
            "type": "string",
            "enum": [
              "marcado",
              "confirmado",
              "concluido",
              "faltou",
              "cancelado"
            ]
          },
          "local": {
            "type": "string"
          },
          "link": {
            "type": "string"
          },
          "notas": {
            "type": "string"
          },
          "contato_id": {
            "type": "string",
            "format": "uuid"
          },
          "conversa_id": {
            "type": "string",
            "format": "uuid"
          },
          "contato": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": "string"
              },
              "telefone": {
                "type": "string"
              },
              "avatar_url": {
                "type": "string"
              }
            }
          },
          "lembretes": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "antes_min": {
                  "type": "integer"
                },
                "estado": {
                  "type": "string"
                },
                "enviar_em": {
                  "type": "string",
                  "format": "date-time"
                },
                "enviado_em": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            }
          },
          "criado_por_tipo": {
            "type": "string"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "confirmado_em": {
            "type": "string",
            "format": "date-time"
          },
          "cancelado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Bloqueio": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agenda_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "titulo": {
            "type": "string"
          },
          "tipo": {
            "type": "string",
            "enum": [
              "folga",
              "almoco",
              "feriado",
              "outro"
            ]
          },
          "inicio": {
            "type": "string",
            "format": "date-time"
          },
          "fim": {
            "type": "string",
            "format": "date-time"
          },
          "fuso": {
            "type": "string"
          },
          "inicio_local": {
            "type": "string",
            "description": "Começo no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          },
          "fim_local": {
            "type": "string",
            "description": "Fim no fuso da agenda, com deslocamento.",
            "example": "2026-10-12T14:00:00-03:00"
          },
          "repetir": {
            "type": "string",
            "enum": [
              "nunca",
              "diario",
              "semanal",
              "anual"
            ]
          },
          "repetir_ate": {
            "type": "string",
            "format": "date"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Membro": {
        "type": "object",
        "description": "Uma pessoa da organização. `id` é o id do usuário. Campos sem valor não aparecem.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "avatar_url": {
            "type": "string"
          },
          "papel": {
            "type": "string",
            "enum": [
              "dono",
              "gestor",
              "atendente"
            ]
          },
          "papel_de_acesso_id": {
            "type": "string",
            "format": "uuid"
          },
          "permissoes": {
            "type": "object",
            "properties": {
              "caixas": {
                "type": "array",
                "items": {
                  "type": "string",
                  "format": "uuid"
                },
                "description": "WhatsApps visíveis. Vazio = todos."
              },
              "modulos": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Módulos liberados. Vazio = todos."
              },
              "agenda": {
                "type": "string",
                "enum": [
                  "todas",
                  "propria"
                ]
              }
            }
          },
          "equipes": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "disponivel": {
            "type": "boolean"
          },
          "disponivel_agora": {
            "type": "boolean"
          },
          "ausente_ate": {
            "type": "string",
            "format": "date-time"
          },
          "horario": {
            "type": "object",
            "description": "{\"dias\": [1,2,3,4,5], \"inicio\": \"08:00\", \"fim\": \"18:00\"} (0 = domingo)."
          },
          "ultimo_acesso": {
            "type": "string",
            "format": "date-time"
          },
          "entrou_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Presenca": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "papel": {
            "type": "string",
            "enum": [
              "dono",
              "gestor",
              "atendente"
            ]
          },
          "disponivel": {
            "type": "boolean"
          },
          "disponivel_agora": {
            "type": "boolean"
          },
          "ausente_ate": {
            "type": "string",
            "format": "date-time"
          },
          "horario": {
            "type": "object"
          },
          "ultimo_acesso": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Convite": {
        "type": "object",
        "description": "Convite aberto. O link nunca aparece aqui (só na resposta de criar/reenviar).",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string"
          },
          "papel": {
            "type": "string",
            "enum": [
              "dono",
              "gestor",
              "atendente"
            ]
          },
          "papel_de_acesso_id": {
            "type": "string",
            "format": "uuid"
          },
          "convidado_por": {
            "type": "string",
            "description": "Nome de quem convidou pela tela. Convites da API não têm."
          },
          "expira_em": {
            "type": "string",
            "format": "date-time"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ConviteComLink": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Convite"
          },
          {
            "type": "object",
            "properties": {
              "link": {
                "type": "string",
                "description": "Link do convite, mostrado UMA vez. Quem tiver o link e o e-mail convidado entra como atendente."
              }
            }
          }
        ]
      },
      "Equipe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "cor": {
            "type": "string"
          },
          "distribuicao": {
            "type": "string",
            "enum": [
              "manual",
              "rodizio",
              "menos_ocupado"
            ]
          },
          "ordem": {
            "type": "integer"
          },
          "membros": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApagadoEquipe": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "apagado": {
            "type": "boolean"
          }
        }
      },
      "RegraComentario": {
        "type": "object",
        "description": "Regra que responde comentários do Instagram. Campos sem valor (null) não aparecem.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "ativo": {
            "type": "boolean"
          },
          "conexao_id": {
            "type": "string",
            "format": "uuid"
          },
          "post_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "palavras": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "modo": {
            "type": "string",
            "enum": [
              "contem",
              "igual"
            ]
          },
          "qualquer_comentario": {
            "type": "boolean"
          },
          "automacao_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "automacao": {
            "type": [
              "string",
              "null"
            ],
            "description": "Nome da automação."
          },
          "responder_publico": {
            "type": [
              "string",
              "null"
            ]
          },
          "resposta_privada": {
            "type": [
              "string",
              "null"
            ]
          },
          "respostas_publicas": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "ocultar_apos": {
            "type": "boolean"
          },
          "botoes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "botoes_detalhe": {
            "type": "array",
            "description": "Os mesmos botões com o link: `url` não aparece no botão que só devolve o toque.",
            "items": {
              "type": "object",
              "properties": {
                "titulo": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                }
              }
            }
          },
          "tipo": {
            "type": "string",
            "enum": [
              "comum",
              "seguir"
            ],
            "description": "`comum` ou `seguir` (\"Seguir para receber\"). Regras antigas são `comum`."
          },
          "seguir": {
            "type": [
              "object",
              "null"
            ],
            "description": "Só no tipo `seguir`: completo, com os padrões aplicados. Não aparece no tipo `comum`; dentro dele, `conteudo.botao`, `max_tentativas` e `texto_limite` também não aparecem enquanto forem null.",
            "properties": {
              "botao_receber": {
                "type": "string",
                "description": "Botão da mensagem do comentário (1 a 20). Padrão: \"Quero receber\"."
              },
              "texto_nao_segue": {
                "type": "string",
                "description": "Para quem ainda não segue (1 a 640)."
              },
              "botao_estou_seguindo": {
                "type": "string",
                "description": "Botão para avisar que passou a seguir (1 a 20). Padrão: \"Estou seguindo\"."
              },
              "texto_ainda_nao_segue": {
                "type": "string",
                "description": "Quando toca em \"Estou seguindo\" e ainda não segue (1 a 640)."
              },
              "texto_ja_segue": {
                "type": "string",
                "description": "Antes do conteúdo, para quem já seguia (0 a 640; \"\" = não envia)."
              },
              "texto_seguiu_depois": {
                "type": "string",
                "description": "Antes do conteúdo, para quem acabou de seguir (0 a 640; \"\" = não envia)."
              },
              "conteudo": {
                "type": "object",
                "description": "O que é entregue.",
                "properties": {
                  "texto": {
                    "type": "string",
                    "description": "1 a 640."
                  },
                  "botao": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "properties": {
                      "titulo": {
                        "type": "string",
                        "description": "1 a 20."
                      },
                      "url": {
                        "type": "string",
                        "description": "https."
                      }
                    }
                  }
                }
              },
              "max_tentativas": {
                "type": [
                  "integer",
                  "null"
                ],
                "minimum": 1,
                "maximum": 50,
                "description": "null = confere até seguir (no máximo 50 vezes)."
              },
              "texto_limite": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Enviada uma vez quando as tentativas acabam (1 a 640)."
              },
              "se_nao_verificar": {
                "type": "string",
                "enum": [
                  "enviar",
                  "pedir_de_novo"
                ],
                "description": "Quando a Meta não deixa conferir. Padrão: `enviar`."
              }
            }
          },
          "estatisticas": {
            "type": [
              "object",
              "null"
            ],
            "description": "Só no tipo `seguir`. Contagem desde que a regra existe.",
            "properties": {
              "pediram": {
                "type": "integer",
                "description": "Pessoas que receberam o botão."
              },
              "entregues": {
                "type": "integer",
                "description": "Pessoas que receberam o conteúdo."
              },
              "ja_seguiam": {
                "type": "integer",
                "description": "Já seguiam ao pedir."
              },
              "seguiram_depois": {
                "type": "integer",
                "description": "Passaram a seguir depois de pedir."
              },
              "aguardando": {
                "type": "integer",
                "description": "Ainda esperando tocar ou seguir."
              }
            }
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          },
          "execucoes_7d": {
            "type": "integer",
            "description": "Disparos nos últimos 7 dias."
          },
          "ultima_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "ContaInstagram": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "caixa_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "usuario": {
            "type": [
              "string",
              "null"
            ]
          },
          "nome": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "AutomacaoResumo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          }
        }
      },
      "ApagadoRegra": {
        "type": "object",
        "properties": {
          "apagado": {
            "type": "boolean"
          }
        }
      },
      "Erro": {
        "type": "object",
        "required": [
          "erro"
        ],
        "properties": {
          "erro": {
            "type": "object",
            "required": [
              "codigo",
              "mensagem",
              "requisicao_id"
            ],
            "properties": {
              "codigo": {
                "type": "string",
                "description": "Estável: use no seu código.",
                "example": "janela_fechada"
              },
              "mensagem": {
                "type": "string",
                "description": "Explicação em português (pode mudar)."
              },
              "detalhe": {
                "type": "string",
                "description": "Campo inválido, escopo que faltou etc."
              },
              "requisicao_id": {
                "type": "string",
                "format": "uuid"
              },
              "ate": {
                "type": "string",
                "format": "date-time",
                "description": "Só em conta_restrita (veja RestricaoMeta). ISO-8601 UTC. GET /me: fim da restrição. 422: quando este tipo de envio volta a sair."
              },
              "desde": {
                "type": "string",
                "format": "date-time",
                "description": "Só em conta_restrita (veja RestricaoMeta). ISO-8601 UTC: primeiro sinal da Meta."
              },
              "ate_fonte": {
                "type": "string",
                "enum": [
                  "meta",
                  "padrao"
                ],
                "description": "Só em conta_restrita (veja RestricaoMeta). meta = data enviada pela Meta (vale ela); padrao = sem data da Meta, agora + horas da trava da organização (estimativa; cada sinal novo estende)."
              },
              "escopo": {
                "type": "string",
                "enum": [
                  "iniciadas",
                  "tudo"
                ],
                "description": "Só em conta_restrita (veja RestricaoMeta). iniciadas = só modelos (conversas que a empresa começa); respostas na janela de 24 h saem. tudo = nenhuma mensagem sai pelo número oficial."
              },
              "motivo": {
                "type": "string",
                "enum": [
                  "meta_131031",
                  "meta_368",
                  "meta_131048",
                  "account_restriction",
                  "account_disabled",
                  "outro"
                ],
                "description": "Só em conta_restrita (veja RestricaoMeta). Código estável do sinal da Meta."
              },
              "motivo_texto": {
                "type": "string",
                "description": "Só em conta_restrita (veja RestricaoMeta). Explicação em português (pode mudar)."
              },
              "caixa_id": {
                "type": "string",
                "format": "uuid",
                "description": "Só em conta_restrita (veja RestricaoMeta)."
              },
              "retry_after_s": {
                "type": "integer",
                "minimum": 1,
                "description": "Só em conta_restrita (veja RestricaoMeta). Segundos até `ate` (no 422, o mesmo valor do cabeçalho Retry-After)."
              }
            }
          }
        }
      },
      "Eu": {
        "type": "object",
        "properties": {
          "organizacao": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": "string"
              }
            }
          },
          "chave": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": "string"
              },
              "prefixo": {
                "type": "string"
              },
              "escopos": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "expira_em": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "limites": {
            "type": "object",
            "properties": {
              "por_minuto": {
                "type": "integer"
              },
              "org_por_minuto": {
                "type": "integer"
              },
              "envios_por_minuto": {
                "type": "integer"
              },
              "envios_org_por_minuto": {
                "type": "integer"
              }
            }
          },
          "trava_spam_meta": {
            "type": "object",
            "description": "Trava de spam da Meta da organização (Configurações > API).",
            "properties": {
              "ligada": {
                "type": "boolean"
              },
              "horas": {
                "type": "integer",
                "description": "Duração da restrição quando a Meta não manda data."
              }
            }
          },
          "caixas": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "nome": {
                  "type": "string"
                },
                "canal": {
                  "type": "string"
                },
                "telefone": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "conexoes": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "tipo": {
                        "type": "string"
                      },
                      "estado": {
                        "type": "string",
                        "description": "nova, aguardando_qr, conectada, desconectada, erro; sem_acesso_meta = API oficial ligada, mas a Meta parou de deixar o FORSI ler a conta (veja sem_acesso_meta)."
                      },
                      "sem_acesso_meta": {
                        "type": "object",
                        "description": "Só quando estado = sem_acesso_meta.",
                        "properties": {
                          "desde": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "ultima_leitura_ok": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      },
                      "restricao_meta": {
                        "$ref": "#/components/schemas/RestricaoMeta"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      },
      "RestricaoMeta": {
        "type": "object",
        "description": "Só aparece enquanto a Meta restringe o número (conexão tipo meta). Ausente = sem restrição.",
        "required": [
          "ate",
          "ate_fonte",
          "escopo",
          "motivo",
          "motivo_texto",
          "caixa_id",
          "retry_after_s",
          "api_recusa",
          "mensagem"
        ],
        "properties": {
          "ate": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 UTC. GET /me: fim da restrição. 422: quando este tipo de envio volta a sair."
          },
          "desde": {
            "type": "string",
            "format": "date-time",
            "description": "ISO-8601 UTC: primeiro sinal da Meta."
          },
          "ate_fonte": {
            "type": "string",
            "enum": [
              "meta",
              "padrao"
            ],
            "description": "meta = data enviada pela Meta (vale ela); padrao = sem data da Meta, agora + horas da trava da organização (estimativa; cada sinal novo estende)."
          },
          "escopo": {
            "type": "string",
            "enum": [
              "iniciadas",
              "tudo"
            ],
            "description": "iniciadas = só modelos (conversas que a empresa começa); respostas na janela de 24 h saem. tudo = nenhuma mensagem sai pelo número oficial."
          },
          "motivo": {
            "type": "string",
            "enum": [
              "meta_131031",
              "meta_368",
              "meta_131048",
              "account_restriction",
              "account_disabled",
              "outro"
            ],
            "description": "Código estável do sinal da Meta."
          },
          "motivo_texto": {
            "type": "string",
            "description": "Explicação em português (pode mudar)."
          },
          "caixa_id": {
            "type": "string",
            "format": "uuid"
          },
          "retry_after_s": {
            "type": "integer",
            "minimum": 1,
            "description": "Segundos até `ate` (no 422, o mesmo valor do cabeçalho Retry-After)."
          },
          "api_recusa": {
            "type": "boolean",
            "description": "true = trava ligada: a API recusa os envios barrados (422 conta_restrita) e campanhas pausam. false = só informa."
          },
          "mensagem": {
            "type": "string",
            "description": "Frase pronta em português para mostrar (pode mudar)."
          }
        }
      },
      "EnvioAceito": {
        "type": "object",
        "properties": {
          "mensagem_id": {
            "type": "string",
            "format": "uuid"
          },
          "conversa_id": {
            "type": "string",
            "format": "uuid"
          },
          "contato_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "caixa_id": {
            "type": "string",
            "format": "uuid"
          },
          "conversa_nova": {
            "type": "boolean"
          },
          "estado": {
            "type": "string",
            "enum": [
              "pendente"
            ]
          }
        }
      },
      "Mensagem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "conversa_id": {
            "type": "string",
            "format": "uuid"
          },
          "direcao": {
            "type": "string",
            "enum": [
              "entrada",
              "saida"
            ]
          },
          "tipo": {
            "type": "string",
            "example": "texto"
          },
          "texto": {
            "type": "string"
          },
          "estado": {
            "type": "string",
            "enum": [
              "pendente",
              "enviando",
              "enviada",
              "entregue",
              "lida",
              "tocada",
              "falhou",
              "recebida",
              "nao_confirmado"
            ],
            "description": "nao_confirmado: a conexão caiu durante o envio e o WhatsApp não confirmou; a mensagem pode ter chegado. Não é reenviada sozinha."
          },
          "erro": {
            "type": "string"
          },
          "autor_tipo": {
            "type": "string",
            "enum": [
              "contato",
              "usuario",
              "agente",
              "sistema",
              "celular"
            ]
          },
          "responde_a_id": {
            "type": "string",
            "format": "uuid"
          },
          "id_whatsapp": {
            "type": "string"
          },
          "enviada_em": {
            "type": "string",
            "format": "date-time"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "editada_em": {
            "type": "string",
            "format": "date-time"
          },
          "apagada_em": {
            "type": "string",
            "format": "date-time"
          },
          "pela_api": {
            "type": "object",
            "properties": {
              "chave_id": {
                "type": "string",
                "format": "uuid"
              }
            }
          },
          "modelo": {
            "type": "string",
            "description": "Nome do modelo, quando tipo = modelo."
          },
          "midia": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid"
                },
                "mime": {
                  "type": "string"
                },
                "nome_arquivo": {
                  "type": "string"
                },
                "tamanho": {
                  "type": "integer"
                },
                "duracao_s": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "Conversa": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "caixa_id": {
            "type": "string",
            "format": "uuid"
          },
          "grupo": {
            "type": "boolean"
          },
          "titulo": {
            "type": [
              "string",
              "null"
            ]
          },
          "estado": {
            "type": "string",
            "enum": [
              "aberta",
              "pendente",
              "adiada",
              "resolvida"
            ]
          },
          "responsavel_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "equipe_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "agente_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "etiquetas": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "nao_lidas": {
            "type": "integer"
          },
          "janela_ate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Até quando a janela de 24 h da API oficial está aberta."
          },
          "ultima_mensagem_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ultima_previa": {
            "type": [
              "string",
              "null"
            ]
          },
          "ultima_direcao": {
            "type": [
              "string",
              "null"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          },
          "resolvida_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "contato": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "telefone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "origem_anuncio": {
            "type": [
              "object",
              "null"
            ],
            "description": "Primeiro anúncio que levou a pessoa ao WhatsApp, Instagram ou Messenger.",
            "properties": {
              "anuncio_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "titulo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "canal": {
                "type": "string"
              },
              "clicado_em": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Contato": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": [
              "string",
              "null"
            ]
          },
          "nome_whatsapp": {
            "type": [
              "string",
              "null"
            ]
          },
          "telefone": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "instagram": {
            "type": [
              "string",
              "null"
            ]
          },
          "campos": {
            "type": "object"
          },
          "bloqueado": {
            "type": "boolean"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          },
          "primeiro_anuncio": {
            "type": [
              "object",
              "null"
            ],
            "description": "Primeiro anúncio que levou a pessoa ao WhatsApp, Instagram ou Messenger.",
            "properties": {
              "anuncio_id": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "titulo": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "canal": {
                "type": "string"
              },
              "clicado_em": {
                "type": "string",
                "format": "date-time"
              }
            }
          }
        }
      },
      "Modelo": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "idioma": {
            "type": "string"
          },
          "categoria": {
            "type": "string"
          },
          "estado": {
            "type": "string",
            "example": "APPROVED"
          },
          "caixa_id": {
            "type": "string",
            "format": "uuid"
          },
          "formato_parametros": {
            "type": "string"
          },
          "variaveis": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "texto": {
            "type": "string"
          },
          "componentes": {
            "type": "array"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "eventos": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "mensagem.recebida",
                "mensagem.enviada",
                "mensagem.status",
                "conversa.criada",
                "conversa.atribuida",
                "conversa.encerrada",
                "contato.criado",
                "negocio.criado",
                "negocio.movido",
                "negocio.ganho",
                "negocio.perdido",
                "agendamento.criado",
                "agendamento.remarcado",
                "agendamento.cancelado",
                "agendamento.confirmado",
                "membro.convidado",
                "membro.entrou",
                "membro.alterado",
                "membro.removido"
              ]
            }
          },
          "ativo": {
            "type": "boolean"
          },
          "segredo_dica": {
            "type": "string",
            "example": "…a1B2c3"
          },
          "segredo_anterior_ate": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "falhas_seguidas": {
            "type": "integer"
          },
          "falhando_desde": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "desativado_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "motivo_desativacao": {
            "type": [
              "string",
              "null"
            ]
          },
          "ultima_entrega_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "ultimo_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          },
          "entregas_24h": {
            "type": "object",
            "properties": {
              "entregues": {
                "type": "integer"
              },
              "falhas": {
                "type": "integer"
              },
              "pendentes": {
                "type": "integer"
              }
            }
          }
        }
      },
      "WebhookComSegredo": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "required": [
              "segredo"
            ],
            "properties": {
              "segredo": {
                "type": "string",
                "description": "Mostrado UMA vez. Guarde num cofre.",
                "example": "whsec_..."
              }
            }
          }
        ]
      },
      "Entrega": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "webhook_id": {
            "type": "string",
            "format": "uuid"
          },
          "evento": {
            "type": "string"
          },
          "evento_id": {
            "type": "string",
            "format": "uuid"
          },
          "estado": {
            "type": "string",
            "enum": [
              "pendente",
              "falhou",
              "entregue",
              "morta",
              "cancelada"
            ]
          },
          "tentativas": {
            "type": "integer"
          },
          "status_http": {
            "type": [
              "integer",
              "null"
            ]
          },
          "resposta": {
            "type": [
              "string",
              "null"
            ]
          },
          "erro": {
            "type": [
              "string",
              "null"
            ]
          },
          "duracao_ms": {
            "type": [
              "integer",
              "null"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "ultima_tentativa_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "proxima_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "entregue_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "payload": {
            "$ref": "#/components/schemas/Evento"
          }
        }
      },
      "TesteAceito": {
        "type": "object",
        "properties": {
          "entrega_id": {
            "type": "string",
            "format": "uuid"
          }
        }
      },
      "Etapa": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "funil_id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "cor": {
            "type": "string",
            "enum": [
              "slate",
              "blue",
              "violet",
              "amber",
              "emerald",
              "green",
              "rose",
              "cyan",
              "orange"
            ]
          },
          "posicao": {
            "type": "integer",
            "description": "Posição no funil, a partir de 0."
          },
          "ganha": {
            "type": "boolean"
          },
          "perdida": {
            "type": "boolean"
          },
          "negocios": {
            "type": "integer",
            "description": "Quantos negócios estão na etapa."
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Funil": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "posicao": {
            "type": "integer"
          },
          "etapas": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Etapa"
            }
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Negocio": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "funil_id": {
            "type": "string",
            "format": "uuid"
          },
          "etapa_id": {
            "type": "string",
            "format": "uuid"
          },
          "etapa": {
            "type": "string",
            "description": "Nome da etapa."
          },
          "estado": {
            "type": "string",
            "enum": [
              "aberto",
              "ganho",
              "perdido"
            ]
          },
          "titulo": {
            "type": "string"
          },
          "valor_centavos": {
            "type": "integer",
            "description": "Em centavos."
          },
          "responsavel_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "previsao": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "contato_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "conversa_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "contato": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "id": {
                "type": "string",
                "format": "uuid"
              },
              "nome": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "telefone": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "ganho_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "perdido_em": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "motivo_perda": {
            "type": [
              "string",
              "null"
            ]
          },
          "posicao": {
            "type": "number",
            "description": "Ordem na coluna (menor = mais acima)."
          },
          "origem": {
            "type": "string",
            "enum": [
              "usuario",
              "agente",
              "sistema",
              "api"
            ],
            "description": "Quem criou."
          },
          "notas": {
            "type": "integer"
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "movido_em": {
            "type": "string",
            "format": "date-time"
          },
          "atualizado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "NotaNegocio": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "negocio_id": {
            "type": "string",
            "format": "uuid"
          },
          "texto": {
            "type": "string"
          },
          "autor_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "autor": {
            "type": [
              "string",
              "null"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ApagadoFunil": {
        "type": "object",
        "properties": {
          "apagado": {
            "type": "boolean"
          },
          "negocios_apagados": {
            "type": "integer"
          },
          "negocios_movidos": {
            "type": "integer"
          }
        }
      },
      "Apagado": {
        "type": "object",
        "properties": {
          "apagado": {
            "type": "boolean"
          },
          "conversas_apagadas": {
            "type": "integer"
          }
        }
      },
      "Evento": {
        "type": "object",
        "required": [
          "id",
          "evento",
          "criado_em",
          "organizacao_id",
          "dados"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "Id do evento: o mesmo em todas as tentativas. Use para não processar duas vezes."
          },
          "evento": {
            "type": "string",
            "enum": [
              "mensagem.recebida",
              "mensagem.enviada",
              "mensagem.status",
              "conversa.criada",
              "conversa.atribuida",
              "conversa.encerrada",
              "contato.criado",
              "negocio.criado",
              "negocio.movido",
              "negocio.ganho",
              "negocio.perdido",
              "agendamento.criado",
              "agendamento.remarcado",
              "agendamento.cancelado",
              "agendamento.confirmado",
              "membro.convidado",
              "membro.entrou",
              "membro.alterado",
              "membro.removido"
            ]
          },
          "criado_em": {
            "type": "string",
            "format": "date-time"
          },
          "organizacao_id": {
            "type": "string",
            "format": "uuid"
          },
          "dados": {
            "type": "object",
            "description": "Eventos de mensagem trazem mensagem + resumo da conversa e do contato; mensagem.status traz também estado_anterior; eventos de conversa trazem conversa + contato; contato.criado traz contato; eventos de negócio (negocio.*) trazem negocio + funil + etapa (negocio.movido traz também etapa_anterior_id e funil_anterior_id). Mover para uma etapa de ganho ou perda dispara negocio.movido e também negocio.ganho / negocio.perdido. membro.convidado traz convite; membro.entrou e membro.alterado trazem membro (membro.alterado também anterior); membro.removido traz membro só com id, papel, nome e email.",
            "properties": {
              "mensagem": {
                "$ref": "#/components/schemas/Mensagem"
              },
              "conversa": {
                "$ref": "#/components/schemas/Conversa"
              },
              "contato": {
                "$ref": "#/components/schemas/Contato"
              },
              "estado_anterior": {
                "type": "string"
              },
              "negocio": {
                "$ref": "#/components/schemas/Negocio"
              },
              "funil": {
                "type": "object"
              },
              "etapa": {
                "type": "object"
              },
              "agendamento": {
                "$ref": "#/components/schemas/Compromisso"
              },
              "anterior": {
                "type": "object",
                "description": "agendamento.remarcado: inicio, fim e agenda_id de antes. membro.alterado: papel, papel_de_acesso_id, modulos e caixas de antes."
              },
              "membro": {
                "$ref": "#/components/schemas/Membro"
              },
              "convite": {
                "$ref": "#/components/schemas/Convite"
              }
            }
          }
        }
      }
    }
  }
}