{
  "formatVersion": 1,
  "language": "pt-BR",
  "instructions": [
    "Escolha o idioma do leitor, leia o fluxo e o endpoint relevantes e consulte o contrato OpenAPI exato. Cite as fontes utilizadas. Estes arquivos não autorizam requisições de negócio reais.",
    "Preserve os hosts, métodos, rotas, autenticação, nomes de campos, tipos, campos obrigatórios e anuláveis, enums, valores padrão, limites e códigos de resposta publicados. As traduções descrevem a mesma API."
  ],
  "schemaScope": "Este corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.",
  "specs": [
    {
      "title": "Bridge API",
      "url": "https://docs.bridge.new/pt-br/api-reference/openapi.yaml",
      "source": "pt-br/api-reference/openapi.yaml"
    },
    {
      "title": "Bridge Campaign Leads API",
      "url": "https://docs.bridge.new/pt-br/api-reference/campaign-leads.openapi.yaml",
      "source": "pt-br/api-reference/campaign-leads.openapi.yaml"
    }
  ],
  "format": "bridge-documentation-collection",
  "title": "Bridge Documentação reunida — Português do Brasil",
  "description": "Este corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.",
  "indexUrl": "https://docs.bridge.new/llms-pt-br.json",
  "pages": [
    {
      "title": "Integre seus sistemas ao Bridge",
      "source": "https://docs.bridge.new/pt-br/index",
      "markdownUrl": "https://docs.bridge.new/pt-br/index.md",
      "description": "Conecte seu CRM, automações ou landing page ao Bridge com a API REST, webhooks e Custom Connections.",
      "kind": "page",
      "contentMarkdown": "Implemente com sua ferramenta de programação preferida\n\n## Conecte seu assistente de programação com IA\n\nConecte sua ferramenta à documentação atual do Bridge. Escolha abaixo para ver a configuração, um exemplo de prompt e o teste de conexão.\n\n  [Codex →](https://docs.bridge.new/pt-br/connect-your-agent.md#codex)\n  [Claude Code →](https://docs.bridge.new/pt-br/connect-your-agent.md#claude-code)\n  [Cursor →](https://docs.bridge.new/pt-br/connect-your-agent.md#cursor)\n  [GitHub Copilot →](https://docs.bridge.new/pt-br/connect-your-agent.md#github-copilot)\n\nO acesso à documentação não exige chave de API do Bridge. O acesso ao workspace é separado.\n\n## Escolha sua integração\n\n  \n\n    \n\n### [API REST](https://docs.bridge.new/pt-br/credentials.md)\n\n      Crie contatos, conversas e mensagens a partir do seu servidor.\n\n      **Acesso:** `x-api-key` no servidor.\n    \n\n    \n\n### [Webhooks](https://docs.bridge.new/pt-br/webhooks.md)\n\n      Receba eventos do Bridge no seu endpoint HTTPS.\n\n      **Acesso:** verifique as credenciais do webhook e a validade temporal.\n    \n\n    \n\n### [Custom Connections](https://docs.bridge.new/pt-br/lead-capture/index.md)\n\n      Capture leads de uma landing page e coloque a mensagem inicial de WhatsApp na fila de envio.\n\n      **Acesso:** `captureKey` e reCAPTCHA; sem chave da API REST.\n    \n\n  \n\n## Faça sua primeira requisição à API REST\n\n  \n\n### Obtenha suas credenciais de API\n\n    Siga o guia de [autenticação](https://docs.bridge.new/pt-br/credentials.md) para gerar uma chave de API no console administrativo do Bridge. Se necessário, peça acesso ao administrador do Bridge. Mantenha a chave no servidor.\n  \n\n  \n\n### Verifique a conexão\n\n    Use o cabeçalho `x-api-key` para chamar o [health check](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md) autenticado em `https://api-connect-us.bridge.new/bridge/api/health`.\n\n    Continue na aba **API REST**. Cada endpoint apresenta seus campos, respostas e exemplos.\n  \n\n**Nota**\n\n  Custom Connections usa um endpoint separado e uma `captureKey` pública. Siga o [guia de integração](https://docs.bridge.new/pt-br/lead-capture/integration.md). Uma resposta `202` confirma a aceitação, não a entrega no WhatsApp.\n\n## Implemente com base no contrato publicado\n\n- [Crie um Contato e envie uma mensagem](https://docs.bridge.new/pt-br/guides/first-conversation.md) — siga o fluxo completo: Contato → conversa → mensagem.\n- [Envie um PDF ou anexo](https://docs.bridge.new/pt-br/guides/send-attachments.md) — checksum, URL de upload, envio do arquivo e mensagem.\n- [Envie um template de WhatsApp](https://docs.bridge.new/pt-br/guides/send-template.md) — descubra as variáveis e forneça os valores exigidos do integrador.\n- [Inicie uma conversa com um Agente e transfira o atendimento](https://docs.bridge.new/pt-br/guides/agent-outbound.md) — escolha o Agente e entenda `forceSend`, reutilização e recuperação.\n- [Consulte identificadores](https://docs.bridge.new/pt-br/guides/identifiers.md) e [percorra os resultados paginados](https://docs.bridge.new/pt-br/guides/pagination.md) — use os IDs e cursores corretos.\n- [Limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md) — compartilhe a cota de requisições e trate respostas `429`.\n- [Códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) — interprete os erros da API REST. Custom Connections tem uma [referência de erros](https://docs.bridge.new/pt-br/lead-capture/errors.md) separada.\n- [Parâmetros de templates de WhatsApp](https://docs.bridge.new/pt-br/templates-and-parameters.md) — abra conversas com templates de WhatsApp e forneça suas variáveis.\n- [Histórico de alterações](https://docs.bridge.new/pt-br/changelog.md) — consulte mudanças que afetam as integrações.\n\nLeia sem MCP pelo [índice trilíngue](https://docs.bridge.new/llms.txt), [índice em português](https://docs.bridge.new/llms-pt-br.json), [documentação reunida em português](https://docs.bridge.new/llms-full-pt-br.json) ou [guia para agentes de IA](https://docs.bridge.new/skill.md). Consulte os esquemas exatos no [OpenAPI da API REST de integrações](https://docs.bridge.new/pt-br/api-reference/openapi.yaml) ou no [OpenAPI de Custom Connections](https://docs.bridge.new/pt-br/api-reference/campaign-leads.openapi.yaml).\n\nPara ajuda sobre o uso do aplicativo Bridge, visite a [Central de Ajuda](https://help.bridge.new).\n"
    },
    {
      "title": "Conecte seu assistente de programação com IA",
      "source": "https://docs.bridge.new/pt-br/connect-your-agent",
      "markdownUrl": "https://docs.bridge.new/pt-br/connect-your-agent.md",
      "description": "Conecte Codex, Claude Code, Cursor ou GitHub Copilot à documentação atual do Bridge e implemente com base no contrato exato da API.",
      "kind": "page",
      "contentMarkdown": "Dê ao seu assistente de programação acesso à documentação atual do Bridge antes de pedir que ele construa a integração. Escolha sua ferramenta abaixo, adicione o endpoint MCP público e faça a verificação de conexão.\n\n| Configuração | Valor |\n| --- | --- |\n| URL do servidor | `https://docs.bridge.new/mcp` |\n| Conexão | HTTP remoto / Streamable HTTP |\n| Nome local sugerido | `bridgeDocs` |\n| Credenciais do Bridge | Nenhuma para esse servidor de documentação |\n\n**Nota**\n\n  Isso conecta seu assistente à **documentação do Bridge**. Não o conecta ao workspace nem concede permissão para criar Contatos ou enviar mensagens. Sua integração usa as [credenciais separadas da API REST](https://docs.bridge.new/pt-br/credentials.md) ou a configuração pública de [Custom Connections](https://docs.bridge.new/pt-br/lead-capture/index.md). O servidor de documentação também oferece uma ferramenta opcional de feedback, que envia comentários sobre a documentação ao Bridge.\n\n## Escolha seu assistente de programação\n\n  \n\n### [Codex](https://docs.bridge.new/pt-br/connect-your-agent.md#codex)\n\nConfiguração da CLI e da extensão local de IDE.\n\n  \n\n### [Claude Code](https://docs.bridge.new/pt-br/connect-your-agent.md#claude-code)\n\nUm comando e, em seguida, a verificação da conexão.\n\n  \n\n### [Cursor](https://docs.bridge.new/pt-br/connect-your-agent.md#cursor)\n\nAdicione o servidor ao arquivo MCP do projeto.\n\n  \n\n### [GitHub Copilot](https://docs.bridge.new/pt-br/connect-your-agent.md#github-copilot)\n\nConfiguração guiada no VS Code ou configuração portátil do projeto.\n\n## Codex\n\n**Antes de começar:** tenha a CLI do Codex ou a extensão Codex para IDE instalada. Para a CLI, adicione o servidor no terminal:\n\n```bash\ncodex mcp add bridgeDocs --url https://docs.bridge.new/mcp\ncodex mcp list\n```\n\nA lista deve incluir `bridgeDocs` com a URL da documentação do Bridge. A presença na lista confirma a configuração; use a [verificação de conexão abaixo](https://docs.bridge.new/pt-br/connect-your-agent.md#check-the-connection) para confirmar que a ferramenta realmente consegue ler a documentação.\n\nSe preferir editar a configuração, adicione esta entrada a `~/.codex/config.toml`. Preserve as demais configurações e entradas de servidores:\n\n```toml\n[mcp_servers.bridgeDocs]\nurl = \"https://docs.bridge.new/mcp\"\n```\n\nReinicie o cliente ou a extensão após alterar a configuração. Na interface de terminal do Codex, `/mcp` mostra os servidores ativos. Clientes locais do Codex podem compartilhar a configuração no mesmo host; ambientes remotos podem ter configuração e políticas separadas.\n\n**Exemplo de prompt:**\n\n> Use bridgeDocs para ler o contrato REST do Bridge e o guia da primeira conversa. Prepare uma integração Node.js que crie um Contato, inicie uma conversa e crie uma mensagem. Liste primeiro os identificadores e as configurações necessários. Mantenha todos os campos e tipos da API inalterados, cite as fontes e não faça requisições reais à API.\n\n[Guia oficial de MCP do Codex](https://learn.chatgpt.com/docs/extend/mcp?surface=cli).\n\n## Claude Code\n\n**Antes de começar:** tenha o Claude Code instalado. Adicione o servidor à configuração pessoal para disponibilizá-lo em todos os projetos:\n\n```bash\nclaude mcp add --transport http bridgeDocs --scope user https://docs.bridge.new/mcp\nclaude mcp list\n```\n\nSe preferir uma configuração compartilhada do projeto, use `--scope project` em vez de `--scope user`. Revise a configuração resultante antes de adicioná-la ao repositório.\n\nInicie o Claude Code e use `/mcp` para inspecionar `bridgeDocs`. Depois, faça a [verificação de conexão abaixo](https://docs.bridge.new/pt-br/connect-your-agent.md#check-the-connection). O endpoint de documentação do Bridge não precisa de uma chave de API do Bridge nem de login OAuth.\n\n**Exemplo de prompt:**\n\n> Use bridgeDocs para ler os guias atuais de verificação e recebimento de webhooks do Bridge. Implemente um receptor Python com a representação HMAC documentada e aceitação persistente antes da confirmação. Adicione testes offline usando o vetor de assinatura publicado. Explique a limitação do timestamp e o tratamento de duplicatas e cite as páginas usadas.\n\n[Guia oficial de MCP do Claude Code](https://code.claude.com/docs/en/mcp).\n\n## Cursor\n\n**Antes de começar:** abra seu projeto de integração no Cursor. Crie ou atualize `.cursor/mcp.json` nesse projeto. Mescle a entrada com os servidores já existentes:\n\n```json\n{\n  \"mcpServers\": {\n    \"bridgeDocs\": {\n      \"url\": \"https://docs.bridge.new/mcp\"\n    }\n  }\n}\n```\n\nPara uma configuração pessoal disponível em vários projetos, use `~/.cursor/mcp.json`. Na barra lateral **Customize** do Cursor, confira se o servidor está habilitado. Abra uma conversa com o Agent e faça a [verificação de conexão abaixo](https://docs.bridge.new/pt-br/connect-your-agent.md#check-the-connection); as ferramentas MCP disponíveis aparecem em **Available Tools**. Revise as solicitações de ferramentas quando o Cursor pedir.\n\n**Exemplo de prompt:**\n\n> Use bridgeDocs para encontrar o fluxo completo de anexos em PDF. Implemente um upload no servidor que calcule o SHA-256 em Base64 dos bytes exatos do arquivo, solicite um upload pré-assinado, execute o PUT exigido e crie uma mensagem com o mediaId retornado. Preserve os campos documentados e explique o tratamento de falhas de cada etapa. Não envie uma chave de API do Bridge à URL de upload.\n\n[Guia oficial de MCP do Cursor](https://cursor.com/docs/mcp).\n\n## GitHub Copilot\n\n**Antes de começar:** habilite o GitHub Copilot no VS Code e abra a pasta do projeto. Selecione **Copilot** como destino da sessão.\n\n1. Abra a paleta de comandos com `Command` + `Shift` + `P` no macOS ou `Ctrl` + `Shift` + `P` no Windows/Linux.\n2. Execute **MCP: Add Server** e escolha **HTTP (HTTP or Server-Sent Events)**.\n3. Informe `https://docs.bridge.new/mcp` e dê ao servidor o nome `bridgeDocs`.\n4. Escolha **Global → Copilot Global** para a configuração pessoal, quando disponível. Revise o destino mostrado pela sua versão do VS Code e qualquer solicitação de confiança no servidor.\n5. Abra uma conversa do Copilot, habilite as ferramentas de documentação do Bridge para a sessão e faça a [verificação de conexão abaixo](https://docs.bridge.new/pt-br/connect-your-agent.md#check-the-connection).\n\nPara um projeto compartilhado usando a configuração portátil atual do Copilot, crie ou mescle esta entrada no arquivo `.mcp.json` na raiz do workspace:\n\n```json\n{\n  \"mcpServers\": {\n    \"bridgeDocs\": {\n      \"type\": \"http\",\n      \"url\": \"https://docs.bridge.new/mcp\",\n      \"tools\": [\"*\"]\n    }\n  }\n}\n```\n\nO formato portátil do Copilot acima é diferente do `.vscode/mcp.json` gerenciado pelo editor, que usa um objeto `servers`. Use o arquivo correspondente à conexão selecionada; não misture os dois formatos. Se o destino portátil não estiver disponível na sua versão, use a configuração guiada e o arquivo escolhido por ela.\n\n**Exemplo de prompt:**\n\n> Use bridgeDocs para ler o guia de Custom Connections e seu contrato OpenAPI separado. Prepare um formulário de landing page que registre o consentimento, obtenha um novo token de CAPTCHA a cada tentativa e apresente uma resposta 202 como aceita com seu requestId. Mantenha captureKey, os campos da requisição e a ação de CAPTCHA configurada inalterados. Não use uma chave da API REST na página.\n\n[Configuração oficial do VS Code](https://code.visualstudio.com/docs/agent-customization/mcp-servers) · [Referência de configuração do Copilot](https://code.visualstudio.com/docs/agents/reference/mcp-configuration).\n\n## Verifique a conexão\n\nDepois de configurar qualquer um dos quatro clientes, faça este pedido:\n\n> Use o servidor MCP de documentação do Bridge para pesquisar a criação de uma mensagem. Leia o esquema MessageRequest no OpenAPI REST publicado. Quais são os três campos obrigatórios? Uma resposta 201 bem-sucedida comprova a entrega pelo WhatsApp? Cite a fonte exata do Bridge que você leu. Não chame a API de negócio.\n\nUma verificação bem-sucedida usa uma ferramenta de documentação e cita uma página ou esquema do Bridge. Ela deve identificar `conversationId`, `messageBody` e `enableExternalBroadcast` como obrigatórios e distinguir uma mensagem criada de um comprovante de entrega do provedor. Uma resposta plausível sem chamada de ferramenta ou fonte não é um teste de conexão.\n\n## Leia a documentação com qualquer IA, sem MCP\n\nNão é necessário conectar o MCP para ler a documentação do Bridge. Forneça a um assistente que possa abrir URLs o [índice trilíngue da documentação](https://docs.bridge.new/llms.txt) e escolha as fontes para sua tarefa e idioma:\n\n| Idioma | Índice de páginas | Documentação reunida |\n| --- | --- | --- |\n| English | [English index](https://docs.bridge.new/llms-en.json) | [English collection](https://docs.bridge.new/llms-full-en.json) |\n| Español | [Índice en español](https://docs.bridge.new/llms-es.json) | [Documentación en español](https://docs.bridge.new/llms-full-es.json) |\n| Português do Brasil | [Índice em português](https://docs.bridge.new/llms-pt-br.json) | [Documentação em português](https://docs.bridge.new/llms-full-pt-br.json) |\n\nO índice aponta para páginas `.md` individuais e para os arquivos OpenAPI exatos. A [coleção completa](https://docs.bridge.new/llms-full.txt) inclui os três idiomas; a coleção de um único idioma é menor. As descrições de endpoints reunidas não substituem os esquemas completos do OpenAPI.\n\nOs arquivos por idioma usam JSON: o índice lista as URLs, e cada coleção contém o texto das páginas em Markdown no campo `contentMarkdown`. Os arquivos gerais `llms.txt` e `llms-full.txt` continuam em Markdown.\n\n**Exemplo de prompt:**\n\n> Leia https://docs.bridge.new/llms.txt e selecione as fontes em português para enviar um PDF. Leia o guia completo de anexos e o OpenAPI REST vinculado antes de escrever código. Explique a sequência de upload, os campos obrigatórios e as limitações de entrega. Preserve as assinaturas publicadas da API e cite as URLs que você leu. Prepare apenas o código; não faça requisições reais.\n\nSe pesquisar pelo MCP, especifique `language: \"pt-BR\"` para português, `language: \"es\"` para espanhol ou `language: \"en\"` para inglês. As páginas públicas usam `.md`; as leituras de páginas no filesystem MCP usam `.mdx`. Consulte também o [guia de capacidades e fontes do Bridge](https://docs.bridge.new/skill.md).\n\n## Implemente com o contrato correto\n\nO servidor oferece pesquisa na documentação, leitura completa de páginas e esquemas em um sistema de arquivos virtual de documentação e feedback opcional sobre a documentação. A ferramenta de sistema de arquivos não executa comandos no seu computador. O feedback é separado da pesquisa e da leitura: use-o somente quando quiser enviar um comentário sobre a documentação.\n\nInforme ao assistente a tarefa e o fluxo correspondente:\n\n- [Primeira conversa](https://docs.bridge.new/pt-br/guides/first-conversation.md): Contato → conversa → mensagem.\n- [Anexos](https://docs.bridge.new/pt-br/guides/send-attachments.md): bytes do arquivo → checksum → PUT pré-assinado → mensagem.\n- [Templates](https://docs.bridge.new/pt-br/guides/send-template.md): descubra as variáveis antes de enviar.\n- [Outbound de Agente](https://docs.bridge.new/pt-br/guides/agent-outbound.md): selecione um Agente e entenda `forceSend`, reutilização e recuperação.\n- [Receptor de webhook](https://docs.bridge.new/pt-br/webhooks/receive-events.md): verifique, persista, confirme e processe.\n\nO [índice da documentação](https://docs.bridge.new/llms.txt) permite localizar páginas. A [documentação reunida](https://docs.bridge.new/llms-full.txt) contém guias e descrições de endpoints, mas não todos os esquemas. Antes de gerar código, leia o Markdown do endpoint ou o [OpenAPI REST](https://docs.bridge.new/pt-br/api-reference/openapi.yaml) ou [OpenAPI de Custom Connections](https://docs.bridge.new/pt-br/api-reference/campaign-leads.openapi.yaml) correspondente.\n\nPeça ao assistente para preservar hosts, métodos, caminhos, autenticação, identificadores, nomes de campos, tipos, campos obrigatórios e anuláveis, enums, valores padrão, limites e códigos de resposta. Se fontes publicadas entrarem em conflito, identifique as passagens e confirme o comportamento atual antes de usá-las como base.\n\n## Se o servidor não aparecer\n\n| Sintoma | O que verificar |\n| --- | --- |\n| Servidor ausente | Confirme o local do arquivo ou o escopo da configuração, o nome do servidor e o cliente ou ambiente usado. Preserve a configuração existente ao adicionar a entrada. |\n| Configurado, mas sem ferramentas | Reinicie ou recarregue o cliente, habilite o servidor e confira o status MCP ou os logs. Uma organização gerenciada pode restringir servidores personalizados. |\n| Solicitação de autenticação | O servidor público de documentação do Bridge não precisa de chave de API do Bridge. Confira a URL e a política do cliente ou da organização. Não cole credenciais do workspace no chat. |\n| Resposta sem citações | Peça explicitamente o uso de `bridgeDocs`, a pesquisa e a leitura do esquema do endpoint. Execute a verificação de conexão novamente. |\n| MCP temporariamente indisponível | Leia diretamente o [índice](https://docs.bridge.new/llms.txt), o Markdown do endpoint e o OpenAPI. O servidor de documentação não tem um compromisso de disponibilidade separado. |\n\nAs interfaces dos clientes mudam com o tempo. As opções de configuração podem variar conforme a versão e a política da organização; use a documentação oficial vinculada se os menus forem diferentes. Instruções dos fornecedores verificadas pela última vez em **14 de novembro de 2026**.\n"
    },
    {
      "title": "Autenticação da API REST",
      "source": "https://docs.bridge.new/pt-br/credentials",
      "markdownUrl": "https://docs.bridge.new/pt-br/credentials.md",
      "description": "Gere e use uma chave de API no servidor para a API REST de integrações, sem confundi-la com as credenciais de webhooks e Custom Connections.",
      "kind": "page",
      "contentMarkdown": "## Visão geral\n\nToda requisição à **API REST de integrações** em `https://api-connect-us.bridge.new` usa uma **chave de API** no cabeçalho `x-api-key`. Essa chave identifica seu aplicativo e autoriza o acesso aos recursos do Bridge em nome da sua organização.\n\n| Tipo de integração | Uso das credenciais |\n| --- | --- |\n| API REST de integrações | `x-api-key` no servidor, enviada para `https://api-connect-us.bridge.new`. |\n| Webhooks | Seu receptor verifica a chave de API configurada para o webhook, a assinatura HMAC e a política de validade do timestamp. Siga o guia de [verificação de assinaturas](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md). |\n| Custom Connections | `captureKey` pública e reCAPTCHA no navegador; sem cabeçalho de autenticação. Siga o [guia de integração](https://docs.bridge.new/pt-br/lead-capture/integration.md). |\n\n**Nota**\n\n  Você precisará de acesso ao console administrativo do Bridge em https://admin.bridge.new.\n\n  Se ainda não tiver acesso, peça ao administrador do Bridge para criar seu usuário.\n\n---\n\n## Gere uma chave de API\n\n  \n\n### Abra o console administrativo\n\n    Acesse o [painel do Bridge](https://admin.bridge.new) e entre com suas credenciais.\n  \n\n  \n\n### Acesse as chaves de API\n\n    No painel esquerdo, acesse **Developers → API Keys Management**.\n  \n\n  \n\n### Crie uma nova chave\n\n    Clique em **Generate New Key**. Você pode definir um nome descritivo e uma data de expiração.\n\n    \n\n**Aviso**\n\n      **Importante:**\\\n      A chave de API será exibida apenas uma vez, no momento da criação. Copie-a imediatamente e guarde-a em um local seguro: você não poderá consultá-la depois.\n    \n\n  \n\n---\n\n## Use sua chave de API\n\nInclua a chave da API REST no cabeçalho `x-api-key` em toda requisição ao host da API REST de integrações:\n\n```bash\ncurl -X GET \"https://api-connect-us.bridge.new/bridge/api/health\" \\\n  -H \"x-api-key: YOUR_API_KEY\"\n```\n\n```javascript\nconst response = await fetch(\"https://api-connect-us.bridge.new/bridge/api/health\", {\n  method: \"GET\",\n  headers: {\n    \"x-api-key\": \"YOUR_API_KEY\",\n  },\n});\n\nconst data = await response.json();\nconsole.log(data);\n```\n\n```python\nimport requests\n\nresponse = requests.get(\n    \"https://api-connect-us.bridge.new/bridge/api/health\",\n    headers={\"x-api-key\": \"YOUR_API_KEY\"}\n)\n\nprint(response.json())\n```\n\n\n**Nota**\n\n  Use o endpoint `GET /bridge/api/health` para verificar se a chave de API é válida e se a conexão está funcionando.\n\n---\n\n## Boas práticas de segurança\n\n- **Use variáveis de ambiente** — Armazene a chave de API em uma variável de ambiente, como `BRIDGE_API_KEY`, em vez de inseri-la diretamente no código-fonte.\n- **Nunca exponha chaves no código do cliente** — As chaves de API devem ser usadas somente em aplicações no servidor. Nunca as inclua no frontend, em aplicativos móveis ou em repositórios públicos.\n- **Defina uma data de expiração** — Sempre configure a expiração ao criar uma chave. Evite chaves sem prazo definido.\n- **Use uma chave por aplicação** — Crie uma chave de API separada para cada serviço ou aplicação que se conecta ao Bridge. Isso limita o impacto de uma chave comprometida.\n- **Faça a rotação das chaves periodicamente** — Crie uma nova chave e atualize as aplicações antes de desativar a antiga. Assim, a rotação não interrompe o serviço.\n\n---\n\n## Solução de problemas\n\n| Erro | Possível causa | Solução |\n| ----- | -------------- | -------- |\n| `401 Unauthorized` | Chave de API inválida, expirada ou ausente | Verifique se a chave está correta, ativa e incluída no cabeçalho `x-api-key` |\n| `403 Forbidden` | A chave de API não tem acesso ao recurso solicitado | Verifique se a chave tem as permissões necessárias para esse endpoint |\n| Não consigo consultar a chave de API | A chave é exibida apenas uma vez, no momento da criação | Gere uma nova chave de API no console administrativo |\n\nPara consultar a lista completa, veja a referência de [códigos de erro](https://docs.bridge.new/pt-br/error-codes.md).\n\n---\n\n## Tópicos relacionados\n\n- [Códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) — Referência completa dos erros da API Bridge\n- [Referência da API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md) — Explore os endpoints disponíveis\n- [Webhooks](https://docs.bridge.new/pt-br/webhooks.md) — Configure notificações de eventos em tempo real\n"
    },
    {
      "title": "Glossário e identificadores",
      "source": "https://docs.bridge.new/pt-br/guides/identifiers",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/identifiers.md",
      "description": "Encontre os identificadores corretos de workspace, Contato, usuário do Bridge, Agente, conversa, template, linha e mídia, sem confundi-los.",
      "kind": "page",
      "contentMarkdown": "## Comece pela integração correta\n\nA **API REST de integrações** lê ou altera recursos do workspace a partir do seu servidor usando `x-api-key`. **Webhooks** enviam eventos do Bridge ao seu receptor. **Custom Connections** registra leads de uma landing page por meio de um endpoint público separado, com `captureKey` e reCAPTCHA.\n\nA chave de API é um segredo do servidor. A `captureKey` de Custom Connections foi projetada para estar na landing page. Esses valores não são intercambiáveis. Veja [autenticação](https://docs.bridge.new/pt-br/credentials.md) e [Custom Connections](https://docs.bridge.new/pt-br/lead-capture/index.md).\n\n## Pessoas, Agentes e linhas\n\n- Um **Contato** é a pessoa externa com quem sua empresa se comunica. Os endpoints de contatos e os participantes externos de conversas se referem a essa pessoa.\n- Um **usuário do Bridge** é um usuário humano interno. A consulta de usuários internos e os destinatários de uma transferência de atendimento se referem a esses usuários.\n- Um **Agente** é um agente automatizado exposto pela API de Agentes. Seu tipo é `LEADSCOUT` ou `SERVICE_AGENT`; ele tem identificador, disponibilidade e linhas próprios.\n- Um **provedor** é um tipo de canal, como `WHATSAPP`. Uma **linha** é um canal específico usado em uma conversa. O tipo de provedor, o telefone e o `providerChannelId` são valores diferentes.\n- Um **workspace** delimita o escopo da requisição. Uma **marca** tem outro identificador, usado onde a operação o exige ou aceita; ela não é um workspace nem uma linha.\n\nO `ownerId` de um Contato se refere a um usuário do Bridge, não a um Agente automatizado. Consulte esse usuário no [endpoint de leitura de usuários internos](https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-id.md).\n\n## De onde vem cada identificador\n\nUse identificadores do workspace desejado. Não reutilize um identificador apenas porque o mesmo telefone, e-mail ou nome aparece em outro workspace.\n\n| Valor necessário | Onde obter ou verificar | O que enviar |\n| --- | --- | --- |\n| `workspaceId` | Use o identificador de workspace fornecido para sua integração. Se não o tiver, peça ao administrador do Bridge. O contrato REST publicado não oferece um endpoint global de listagem de workspaces. | O ID do workspace no caminho da operação. Custom Connections também o exige no corpo e, para requisições do navegador, na query string. |\n| ID do Contato | [Consulte um Contato](https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador.md) por `PHONE`, `EMAIL` ou `ID`; respostas de listagem, criação e upsert também retornam o `id` do Contato. | O `id` retornado em `{contactId}` ou em um objeto identificador com `identifierType: \"ID\"`, onde a operação aceitar esse formato. |\n| ID do usuário do Bridge | [Consulte um usuário interno](https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-um-identificador.md) por `EMAIL` ou `ID`, ou use a lista de usuários internos. | O `id` retornado em `{userId}` ou em um objeto identificador interno. A consulta de usuários internos não aceita `PHONE`. |\n| ID do Agente | [Liste os Agentes](https://docs.bridge.new/pt-br/api-reference/agents-api/listar-os-agents-de-um-workspace.md). Leia `agents[].id`, `type` e `available`. | `agents[].id` em `{agentId}` na operação outbound de Agente. `available` indica se o Agente pode iniciar conversas. |\n| ID da linha do Agente | Na mesma resposta de Agentes, leia `lines[].providerChannelId` do Agente correspondente. | Um ID de linha pertencente ao Agente quando a operação aceitar `contact.providerChannelId`. Consulte as regras de seleção de linha na referência outbound. |\n| Canal de provedor em geral | [Liste os canais de provedor](https://docs.bridge.new/pt-br/api-reference/provider-channels-api/obter-canais-de-provedores-por-workspace.md). Essa resposta publica `provider` e `identifier`, não o UUID do canal. | Use esses campos somente para as finalidades documentadas pela operação que os recebe. Não substitua `providerChannelId` pelo `identifier`, que tem formato de telefone. |\n| `brandId` | Uma resposta de Agente pode expor seu `brandId`. Para outro fluxo, obtenha o ID da marca na configuração da integração ou com o administrador; o contrato publicado não oferece um endpoint geral de listagem de marcas. | O ID de marca aceito pela operação. Um ID de marca não é um ID de linha. |\n| `teamId` | Obtenha o ID da equipe interna desejada com o administrador do Bridge ou na configuração da integração. O contrato REST publicado não oferece um endpoint de listagem de equipes. | A opção documentada de atribuição de equipe na criação da conversa; não envie também `participants.internals`. |\n| ID da conversa | Crie ou consulte uma conversa e guarde o `id` retornado. As respostas outbound contêm `conversation.id`. | `{conversationId}` ou `conversationId`, exatamente onde a operação exigir. |\n| Template | [Descubra um template](https://docs.bridge.new/pt-br/api-reference/templates-api/descobrir-as-vari%C3%A1veis-agn%C3%B3sticas-de-um-modelo.md) por ID ou nome. A resposta retorna `id`, `name` e as chaves das variáveis. | Use o seletor esperado pela operação de envio; veja a próxima seção. |\n| `mediaId` | [Crie uploads pré-assinados](https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos.md). Cada item do array de resposta contém `mediaId` e `presignUrl`. Conclua o upload PUT obrigatório. | O `mediaId` retornado em `mediaIds` ou no campo de mídia aceito pela operação. Não envie a URL pré-assinada como ID de mídia. |\n\n**Nota**\n\n  As listagens de Agentes expõem IDs de linha no contexto de cada Agente. Isso não é uma forma geral de descobrir todas as linhas do workspace. Se outro fluxo exigir um `providerChannelId` que você não consegue obter da resposta publicada, peça ao administrador do Bridge ou ao [suporte](mailto:support@sainapsis.com) o ID da linha desejada. Não gere um ID nem o derive de um telefone.\n\n## Nomes semelhantes podem exigir campos diferentes\n\nA **consulta de contatos** recebe parâmetros de query chamados `type` e `value`. Um participante externo de conversa recebe `identifier` e `identifierType`, além dos demais campos exigidos pela operação. Não copie diretamente a query de consulta para o corpo de um participante.\n\nA **descoberta de templates** aceita ID ou nome no parâmetro de caminho `{templateId}`. Os **templates iniciais de conversa** usam `onboardingTemplates[].templateId`. A **seleção de template outbound** usa `id` ou `name` no objeto `template`; leia o esquema do endpoint em vez de renomear todos os seletores para `templateId`.\n\nUse a `key` retornada para cada variável em `parameters` do template. As chaves das variáveis não são índices de posições da Meta. O [guia de parâmetros de templates](https://docs.bridge.new/pt-br/templates-and-parameters.md) explica valores obrigatórios, padrões e a diferença entre omitir um valor e enviá-lo vazio.\n\n## Não confunda os identificadores de resultado\n\n| Valor retornado | O que identifica | O que não comprova por si só |\n| --- | --- | --- |\n| `messageId` | Uma mensagem criada pelo endpoint de mensagens | Um comprovante de entrega do provedor |\n| `trackingId` | Uma solicitação aceita de transferência LeadScout | A conclusão da atribuição aos usuários solicitados |\n| `requestId` | Um envio aceito de Custom Connections | A entrega da mensagem inicial de WhatsApp |\n| `eventId` | Um identificador enviado com o evento de webhook; algumas famílias usam valores derivados da entidade | Uma chave de deduplicação globalmente única ou garantia de ordem de entrega |\n\nSiga o guia de [recebimento de eventos](https://docs.bridge.new/pt-br/webhooks/receive-events.md) para entender a identidade dos eventos e tratar duplicatas. Veja [respostas e erros](https://docs.bridge.new/pt-br/guides/responses.md) para interpretar códigos de status, resultados assíncronos e novas tentativas. Para um fluxo completo, siga o guia da [primeira conversa](https://docs.bridge.new/pt-br/guides/first-conversation.md) ou de [envio de anexos](https://docs.bridge.new/pt-br/guides/send-attachments.md).\n"
    },
    {
      "title": "Crie um contato e envie uma mensagem",
      "source": "https://docs.bridge.new/pt-br/guides/first-conversation",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/first-conversation.md",
      "description": "Siga um fluxo completo no servidor, do Contato à conversa e à mensagem, preservando os identificadores retornados.",
      "kind": "page",
      "contentMarkdown": "Este guia cria um Contato, inicia uma conversa com um usuário interno do Bridge e cria uma mensagem. Execute o exemplo no seu servidor.\n\n**Aviso**\n\n  Use um Contato de teste para o qual você tem autorização de envio. A criação da conversa pode executar os templates iniciais do workspace antes da requisição separada de mensagem. Revise essa configuração primeiro: definir como false o sinalizador de envio externo da mensagem posterior não desabilita os templates iniciais da conversa.\n\n## Antes de começar\n\n- Obtenha uma chave de API para uso no servidor no guia de [autenticação](https://docs.bridge.new/pt-br/credentials.md).\n- Tenha o ID do workspace, o `providerChannelId` de uma linha ativa de WhatsApp e o e-mail de um usuário interno do Bridge. Veja [conceitos e identificadores](https://docs.bridge.new/pt-br/guides/identifiers.md).\n- Use um novo telefone de teste em formato internacional. Se o Contato já existir, use a [consulta de contatos](https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador.md) em vez de criá-lo novamente.\n- Verifique os atributos personalizados obrigatórios e a sequência inicial configurada no workspace. Este exemplo mínimo não envia atributos personalizados nem substitui os templates.\n- Escolha `enableExternalBroadcast` explicitamente: `true` solicita o envio externo quando as regras da conversa e do destinatário permitem; `false` ainda cria a mensagem, mas não realiza o envio externo. Nenhum dos valores confirma a entrega pelo provedor. Esse sinalizador não ignora regras de visibilidade ou permissões.\n\n## A sequência\n\n| Etapa | Requisição | Valor a guardar |\n| --- | --- | --- |\n| Verificar o acesso | `GET /bridge/api/health` | Resposta HTTP bem-sucedida |\n| Criar Contato | `POST /bridge/api/v1/workspaces/{workspaceId}/contacts` | `id` do Contato |\n| Iniciar conversa | `POST /bridge/api/v1/workspaces/{workspaceId}/conversations` | `id` da conversa |\n| Criar mensagem | `POST /bridge/api/v1/workspaces/{workspaceId}/messages` | `messageId` |\n\nO `id` do Contato passa a ser o `identifier` do participante externo, com `identifierType: \"ID\"`. O `id` da conversa passa a ser o `conversationId` da mensagem.\n\n## Execute o exemplo\n\nUse Node.js com `fetch` nativo. Salve como `first-conversation.mjs`. Configure estas variáveis de ambiente no servidor, usando os recursos de segredos e configuração da sua aplicação:\n\n| Variável | Valor |\n| --- | --- |\n| `BRIDGE_API_KEY` | Sua chave de API secreta |\n| `BRIDGE_WORKSPACE_ID` | O ID do workspace desejado |\n| `BRIDGE_PROVIDER_CHANNEL_ID` | O ID da linha de WhatsApp autorizada, não seu telefone |\n| `BRIDGE_USER_EMAIL` | Um usuário interno do Bridge no mesmo workspace |\n| `TEST_CONTACT_PHONE` | O telefone de um novo Contato de teste autorizado |\n| `ENABLE_EXTERNAL_BROADCAST` | Exatamente `true` ou `false`; nenhum valor padrão é presumido |\n\nOs nomes e a mensagem abaixo são exemplos. Substitua-os pelo conteúdo de teste desejado antes de executar.\n\n```javascript\nconst BASE = \"https://api-connect-us.bridge.new\";\n\nfunction required(name) {\n  const value = process.env[name];\n  if (!value) throw new Error(`Set ${name} before running this example.`);\n  return value;\n}\n\nconst apiKey = required(\"BRIDGE_API_KEY\");\nconst workspaceId = required(\"BRIDGE_WORKSPACE_ID\");\nconst providerChannelId = required(\"BRIDGE_PROVIDER_CHANNEL_ID\");\nconst internalEmail = required(\"BRIDGE_USER_EMAIL\");\nconst cellphone = required(\"TEST_CONTACT_PHONE\");\nconst broadcast = required(\"ENABLE_EXTERNAL_BROADCAST\");\nif (![\"true\", \"false\"].includes(broadcast)) {\n  throw new Error(\"ENABLE_EXTERNAL_BROADCAST must be true or false.\");\n}\nconst workspacePath = `/bridge/api/v1/workspaces/${encodeURIComponent(workspaceId)}`;\n\nasync function request(method, path, body, expectedStatus) {\n  const response = await fetch(`${BASE}${path}`, {\n    method,\n    headers: {\n      \"x-api-key\": apiKey,\n      ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n    },\n    ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n  });\n  const result = await response.json().catch(() => null);\n  if (response.status !== expectedStatus) {\n    const code = result?.code ? ` (${result.code})` : \"\";\n    throw new Error(`${method} ${path}: HTTP ${response.status}${code}`);\n  }\n  return result;\n}\n\nawait request(\"GET\", \"/bridge/api/health\", undefined, 200);\n\nconst contact = await request(\"POST\", `${workspacePath}/contacts`, {\n  firstName: \"Alex\",\n  lastName: \"Example\",\n  languageCode: \"EN\",\n  cellphone,\n}, 201);\nif (!contact?.id || contact.workspaceId !== workspaceId) {\n  throw new Error(\"The Contact response does not identify the intended workspace.\");\n}\n\nconst conversation = await request(\"POST\", `${workspacePath}/conversations`, {\n  participants: {\n    externals: [{\n      identifier: contact.id,\n      identifierType: \"ID\",\n      messageProviderType: \"WHATSAPP\",\n      providerChannelId,\n    }],\n    internals: [{ identifier: internalEmail, identifierType: \"EMAIL\" }],\n  },\n  name: \"Integration test\",\n  status: \"ACTIVE\",\n}, 201);\nif (!conversation?.id || conversation.workspaceId !== workspaceId) {\n  throw new Error(\"The Conversation response does not identify the intended workspace.\");\n}\n\nconst message = await request(\"POST\", `${workspacePath}/messages`, {\n  conversationId: conversation.id,\n  messageBody: \"Hello from our authorized Bridge integration test.\",\n  enableExternalBroadcast: broadcast === \"true\",\n}, 201);\nif (!message?.messageId) throw new Error(\"The Message response has no messageId.\");\n\nconsole.log({\n  contactId: contact.id,\n  conversationId: conversation.id,\n  messageId: message.messageId,\n});\n```\n\n```bash\nnode first-conversation.mjs\n```\n\n\n## Entenda o resultado\n\n- Uma resposta `201` de Contato informa sua identidade e workspace. Leia `type` para verificar a classificação real: `NORMAL` ou `PARTIAL`.\n- Uma resposta `201` de conversa fornece o ID a usar na próxima etapa. Quando nenhuma linha está livre, o Bridge pode recuperar uma conversa liberada com exatamente os participantes solicitados. Nesse caso, o ID e o histórico são mantidos, e os valores solicitados de `name` e `status` não são aplicados.\n- Uma resposta `201` de mensagem fornece `messageId`. Isso, por si só, não comprova que o WhatsApp entregou a mensagem ao Contato.\n\nEste guia atribui explicitamente um usuário interno do Bridge. Para atribuir uma equipe, use a opção documentada `teamId` em vez de `participants.internals`: as duas opções são mutuamente exclusivas.\n\n## Se uma etapa falhar\n\nO exemplo para na requisição que falhou e nunca repete uma operação de escrita automaticamente. Uma falha de rede pode deixar o resultado incerto. Consulte o recurso correspondente antes de repetir uma criação ou um envio.\n\n| Situação | Próxima ação |\n| --- | --- |\n| O Contato já existe | Use a consulta de contatos e o `id` retornado; não continue criando o mesmo Contato. |\n| Erro de marca ou linha | Confirme a linha ou marca autorizada com o administrador; o telefone de uma linha não é seu ID. |\n| Erro de template `0604`–`0608` | Consulte [parâmetros de templates de WhatsApp](https://docs.bridge.new/pt-br/templates-and-parameters.md), incluindo os erros de configuração do workspace. |\n| Mensagem rejeitada porque a conversa está liberada | Verifique o estado da conversa e a referência de erros da operação antes de realizar outra ação. |\n| `429` | Siga o guia de [limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md), incluindo `Retry-After`. |\n\nVeja [respostas e erros](https://docs.bridge.new/pt-br/guides/responses.md) para conhecer os formatos de resposta e decidir como recuperar a operação.\n\n## Próximos passos\n\n- [Faça upload e envie um anexo](https://docs.bridge.new/pt-br/guides/send-attachments.md).\n- [Escolha e preencha um template de WhatsApp](https://docs.bridge.new/pt-br/guides/send-template.md).\n- Consulte os contratos completos de requisição e resposta para [criar um Contato](https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-contato.md), [criar uma conversa](https://docs.bridge.new/pt-br/api-reference/conversations-api/criar-conversa-com-identifica%C3%A7%C3%A3o-flex%C3%ADvel-de-usu%C3%A1rios.md) e [criar uma mensagem](https://docs.bridge.new/pt-br/api-reference/messages-api/criar-mensagem.md).\n"
    },
    {
      "title": "Enviar PDF e outros anexos",
      "source": "https://docs.bridge.new/pt-br/guides/send-attachments",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/send-attachments.md",
      "description": "Envie um PDF ou outro arquivo compatível em uma conversa: calcule o checksum, faça upload na URL pré-assinada e anexe o ID de mídia à mensagem.",
      "kind": "page",
      "contentMarkdown": "Para enviar um PDF ou outro anexo compatível, solicite um upload ao Bridge, envie os bytes do arquivo à URL retornada e crie uma mensagem com o `mediaId` recebido. O exemplo completo no servidor abaixo envia um PDF.\n\n## Antes de começar\n\n- Tenha uma conversa existente no workspace desejado. Veja [primeira conversa](https://docs.bridge.new/pt-br/guides/first-conversation.md).\n- Escolha um PDF que você tem autorização para compartilhar e confirme se ele atende aos limites da [API de arquivos](https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos.md).\n- Mantenha a chave de API do Bridge no servidor. Não a acrescente à requisição de upload pré-assinada.\n- Escolha explicitamente o sinalizador `enableExternalBroadcast` da mensagem.\n\n## Valide o arquivo antes de solicitar um upload\n\nVerifique o arquivo real no seu servidor: a extensão, o tipo MIME e o tamanho em bytes devem cumprir as regras publicadas da [API de arquivos](https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos.md). A requisição de URL pré-assinada contém metadados e um checksum, não os bytes do arquivo nem um campo de tamanho. Uma resposta `201` prepara um upload; não comprova que os bytes reais foram inspecionados, que o tamanho enviado cumpre os limites publicados ou que um provedor de mensagens aceitará o arquivo.\n\nSe você omitir `contentType`, ainda assim copie `presignUrl.headers` para a requisição PUT: a Bridge pode deduzir `Content-Type` pelo nome do arquivo. Se o informar, use o tipo MIME do arquivo real e mantenha-o coerente com `fileType` e a extensão. Renomear um arquivo não converte seu conteúdo.\n\nApós um PUT bem-sucedido, o processamento do upload ainda pode estar pendente. Se uma requisição de Message retornar um [erro de upload de arquivos](https://docs.bridge.new/pt-br/error-codes.md#file-upload-errors), preserve o erro completo e confira a etapa que falhou antes de decidir se outra gravação é segura.\n\n## Sequência de upload\n\n| Etapa | O que acontece | O que ela não confirma |\n| --- | --- | --- |\n| `POST .../files` | O Bridge retorna `mediaId` e os dados de `presignUrl`. | Os bytes ainda não foram enviados. |\n| `PUT` pré-assinado | Seu servidor envia exatamente os bytes do arquivo usando a URL de upload e os cabeçalhos retornados. | Essa etapa não cria uma mensagem. |\n| `POST .../messages` | Você anexa o `mediaId` do arquivo enviado por meio de `mediaIds`. | A resposta da API, sozinha, não comprova a entrega pelo provedor. |\n\nO checksum é o **digest SHA-256 de todos os bytes do arquivo, codificado em Base64**. Não é um digest hexadecimal nem o hash do nome do arquivo.\n\n## Exemplo completo no servidor\n\nUse Node.js com `fetch` nativo. Salve como `send-attachment.mjs`. Defina `BRIDGE_API_KEY`, `BRIDGE_WORKSPACE_ID`, `BRIDGE_CONVERSATION_ID`, `ATTACHMENT_PATH` e `ENABLE_EXTERNAL_BROADCAST` (`true` ou `false`).\n\n```javascript\nimport { readFile } from \"node:fs/promises\";\nimport { basename } from \"node:path\";\nimport { createHash } from \"node:crypto\";\n\nconst BASE = \"https://api-connect-us.bridge.new\";\nfunction required(name) {\n  const value = process.env[name];\n  if (!value) throw new Error(`Set ${name} before running this example.`);\n  return value;\n}\nconst apiKey = required(\"BRIDGE_API_KEY\");\nconst workspaceId = required(\"BRIDGE_WORKSPACE_ID\");\nconst conversationId = required(\"BRIDGE_CONVERSATION_ID\");\nconst filePath = required(\"ATTACHMENT_PATH\");\nconst broadcast = required(\"ENABLE_EXTERNAL_BROADCAST\");\nif (![\"true\", \"false\"].includes(broadcast)) {\n  throw new Error(\"ENABLE_EXTERNAL_BROADCAST must be true or false.\");\n}\nif (!filePath.toLowerCase().endsWith(\".pdf\")) {\n  throw new Error(\"This example is configured for a PDF document.\");\n}\nconst workspacePath = `/bridge/api/v1/workspaces/${encodeURIComponent(workspaceId)}`;\nconst bytes = await readFile(filePath);\nconst checksumBase64 = createHash(\"sha256\").update(bytes).digest(\"base64\");\n\nasync function bridgePost(path, body) {\n  const response = await fetch(`${BASE}${workspacePath}${path}`, {\n    method: \"POST\",\n    headers: { \"x-api-key\": apiKey, \"Content-Type\": \"application/json\" },\n    body: JSON.stringify(body),\n  });\n  const result = await response.json().catch(() => null);\n  if (response.status !== 201) {\n    const code = result?.code ? ` (${result.code})` : \"\";\n    throw new Error(`Bridge ${path}: HTTP ${response.status}${code}`);\n  }\n  return result;\n}\n\nconst uploads = await bridgePost(\"/files\", [{\n  name: basename(filePath),\n  fileType: \"DOCUMENT\",\n  contentType: \"application/pdf\",\n  checksumBase64,\n}]);\nconst upload = uploads?.[0];\nif (!upload?.mediaId || !upload.presignUrl?.url) {\n  throw new Error(\"The upload response is missing its mediaId or URL.\");\n}\nconst method = upload.presignUrl.method ?? \"PUT\";\nif (method !== \"PUT\") throw new Error(\"Expected a presigned PUT upload.\");\nconst uploadHeaders = new Headers(upload.presignUrl.headers ?? {});\nconst returnedChecksum = uploadHeaders.get(\"x-amz-checksum-sha256\");\nif (returnedChecksum !== null && returnedChecksum !== checksumBase64) {\n  throw new Error(\"The returned checksum differs from the file checksum.\");\n}\nif (returnedChecksum === null) {\n  uploadHeaders.set(\"x-amz-checksum-sha256\", checksumBase64);\n}\n\nconst uploaded = await fetch(upload.presignUrl.url, {\n  method,\n  headers: uploadHeaders,\n  body: bytes,\n});\nif (!uploaded.ok) {\n  throw new Error(`File upload failed: HTTP ${uploaded.status}; no Message was created.`);\n}\n\nconst message = await bridgePost(\"/messages\", {\n  conversationId,\n  messageBody: \"Here is the document you requested.\",\n  enableExternalBroadcast: broadcast === \"true\",\n  mediaIds: [upload.mediaId],\n});\nif (!message?.messageId) throw new Error(\"The Message response has no messageId.\");\nconsole.log({ mediaId: upload.mediaId, messageId: message.messageId });\n```\n\n```bash\nnode send-attachment.mjs\n```\n\n\n## Preserve a requisição de upload\n\nUse `presignUrl.url` sem reconstruir o host, o caminho ou a query string. Use o método e os cabeçalhos obrigatórios retornados. O contrato define `PUT` como método padrão quando o campo é omitido, e a API de arquivos exige `x-amz-checksum-sha256` com o mesmo checksum enviado ao Bridge.\n\nO upload envia os mesmos `bytes` usados para calcular o checksum. Não converta o PDF em texto, não o encapsule em JSON e não envie uma cópia diferente após calcular o hash.\n\nPara vários arquivos, preserve a associação entre cada `mediaId` retornado, os dados pré-assinados e o arquivo correspondente. Conclua todos os uploads necessários antes de anexar os IDs a uma mensagem.\n\nAlgumas mídias precisam de mais preparação após o upload, como copiar o arquivo, gerar uma prévia, converter ou enviar o arquivo ao provedor de mensagens. Essas etapas podem falhar de forma independente. Um PUT bem-sucedido ou uma resposta 201 ao criar a mensagem não comprovam que o processamento ou a entrega pelo provedor foram concluídos. Mantenha o arquivo original e os identificadores recebidos para correlacionar o resultado antes de repetir uma requisição de mensagem.\n\n## Trate uma falha em cada etapa\n\n- **O Bridge rejeita a solicitação de arquivo:** confira extensão, `fileType`, tipo de conteúdo, tamanho e checksum na referência.\n- **O upload falha:** pare antes de criar a mensagem. Verifique URL, método, cabeçalhos, checksum e bytes exatos. Não presuma um prazo de validade ou uma política de novas tentativas que a resposta não informe.\n- **A requisição de mensagem falha ou expira:** um arquivo enviado não comprova a existência de uma mensagem. Verifique o resultado antes de repetir a requisição de mensagem.\n\n`STICKER` e `WEBSITE` aparecem no enum `FileType`, mas a tabela pública de upload não especifica suas regras de extensão, MIME e tamanho. Confirme essas regras antes de escolher qualquer um deles para uma integração.\n\nVeja a [API de arquivos](https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos.md), a [API de mensagens](https://docs.bridge.new/pt-br/api-reference/messages-api/criar-mensagem.md) e o guia de [respostas e erros](https://docs.bridge.new/pt-br/guides/responses.md).\n"
    },
    {
      "title": "Escolha e preencha um template de WhatsApp",
      "source": "https://docs.bridge.new/pt-br/guides/send-template",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/send-template.md",
      "description": "Descubra um template por ID ou nome, forneça os valores por suas chaves de variável agnósticas e use o ID retornado em uma requisição de conversa.",
      "kind": "page",
      "contentMarkdown": "Use este guia quando quiser abrir uma conversa com um template específico de WhatsApp. A [referência detalhada de templates](https://docs.bridge.new/pt-br/templates-and-parameters.md) explica as regras de validação e todos os erros de template documentados.\n\n## Antes de começar\n\n- Tenha o **ID ou nome** do template. Ambos são aceitos por `GET .../templates/{templateId}`.\n- Confirme que o template foi aprovado para a conta WhatsApp Business associada à linha desejada.\n- Tenha o ID de um Contato de teste existente, o `providerChannelId` da linha autorizada de WhatsApp e o e-mail de um usuário interno do Bridge. Veja [conceitos e identificadores](https://docs.bridge.new/pt-br/guides/identifiers.md).\n- Revise a sequência inicial do workspace: sua substituição pode trocar toda a sequência ou apenas o primeiro template, conforme a configuração.\n\n**Aviso**\n\n  A requisição final inicia uma conversa e pode enviar os templates iniciais. Use um Contato de teste autorizado e o conteúdo pretendido.\n\n## 1. Descubra as variáveis\n\n```http\nGET /bridge/api/v1/workspaces/{workspaceId}/templates/{templateId}\nx-api-key: YOUR_API_KEY\n```\n\nCodifique o ID ou nome fornecido para uso na URL. Leia `id`, `name`, `variables` e `driftWarning` na resposta.\n\n| Variável | Ação |\n| --- | --- |\n| `callerMustSupply: true` | Forneça uma string não vazia na `key` dessa variável. |\n| `callerMustSupply: false`, não personalizada | Omita-a para manter o valor definido pelo Bridge para cada Contato. Um valor informado substitui esse valor para todos os Contatos. |\n| `isCustom: true` | Forneça seu valor ou omita-o ou envie-o vazio para usar o `default`. |\n\nUse a `key` agnóstica, nunca o `label` de exibição, uma posição da Meta ou um nome de variável inventado. `driftWarning` é diagnóstico e, por si só, não bloqueia o envio.\n\n## 2. Prepare seus valores\n\nCrie um arquivo JSON no servidor contendo somente as chaves retornadas pela descoberta. Para um template que realmente declare `order_number` e `delivery_date`, ele poderia conter:\n\n```json\n{\n  \"order_number\": \"A-10492\",\n  \"delivery_date\": \"October 3\"\n}\n```\n\nEsses dois nomes são exemplos, não campos universais do Bridge. Consulte seu próprio template antes de usá-los. Mantenha os valores dentro das [regras de valores do WhatsApp](https://docs.bridge.new/pt-br/templates-and-parameters.md#whatsapp-value-rules). Para valores não personalizados que você quer que o Bridge preencha, omita as chaves em vez de enviar strings vazias.\n\n## 3. Descubra, valide e crie a conversa\n\nUse Node.js com `fetch` nativo. Salve como `send-template.mjs` e defina `BRIDGE_API_KEY`, `BRIDGE_WORKSPACE_ID`, `BRIDGE_TEMPLATE_ID_OR_NAME`, `TEMPLATE_VALUES_PATH`, `BRIDGE_CONTACT_ID`, `BRIDGE_PROVIDER_CHANNEL_ID` e `BRIDGE_USER_EMAIL`.\n\n```javascript\nimport { readFile } from \"node:fs/promises\";\n\nconst BASE = \"https://api-connect-us.bridge.new\";\nfunction required(name) {\n  const value = process.env[name];\n  if (!value) throw new Error(`Set ${name} before running this example.`);\n  return value;\n}\nconst apiKey = required(\"BRIDGE_API_KEY\");\nconst workspaceId = required(\"BRIDGE_WORKSPACE_ID\");\nconst templateRef = required(\"BRIDGE_TEMPLATE_ID_OR_NAME\");\nconst contactId = required(\"BRIDGE_CONTACT_ID\");\nconst providerChannelId = required(\"BRIDGE_PROVIDER_CHANNEL_ID\");\nconst internalEmail = required(\"BRIDGE_USER_EMAIL\");\nconst parameters = JSON.parse(await readFile(required(\"TEMPLATE_VALUES_PATH\"), \"utf8\"));\nif (parameters === null || Array.isArray(parameters) || typeof parameters !== \"object\") {\n  throw new Error(\"The template values file must contain a JSON object.\");\n}\nif (Object.entries(parameters).some(([key, value]) =>\n  Array.from(key).length > 128 || typeof value !== \"string\" || Array.from(value).length > 1024\n)) {\n  throw new Error(\"Parameter keys and values must respect the published string limits.\");\n}\nif (Object.keys(parameters).length > 50) throw new Error(\"At most 50 parameters are allowed.\");\nconst workspacePath = `/bridge/api/v1/workspaces/${encodeURIComponent(workspaceId)}`;\n\nasync function request(method, path, body, expectedStatus) {\n  const response = await fetch(`${BASE}${workspacePath}${path}`, {\n    method,\n    headers: {\n      \"x-api-key\": apiKey,\n      ...(body === undefined ? {} : { \"Content-Type\": \"application/json\" }),\n    },\n    ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n  });\n  const result = await response.json().catch(() => null);\n  if (response.status !== expectedStatus) {\n    const code = result?.code ? ` (${result.code})` : \"\";\n    throw new Error(`${method} ${path}: HTTP ${response.status}${code}`);\n  }\n  return result;\n}\n\nconst template = await request(\n  \"GET\", `/templates/${encodeURIComponent(templateRef)}`, undefined, 200,\n);\nif (!template?.id) throw new Error(\"Template discovery returned no id.\");\nconst variables = template.variables ?? [];\nconst known = new Set(variables.map((variable) => variable.key));\nconst unknown = Object.keys(parameters).filter((key) => !known.has(key));\nconst missing = variables.filter((variable) =>\n  variable.callerMustSupply &&\n  (typeof parameters[variable.key] !== \"string\" || !parameters[variable.key].trim())\n);\nif (unknown.length || missing.length) {\n  throw new Error(`Check template keys: ${unknown.length} unknown, ${missing.length} missing.`);\n}\n\nconst conversation = await request(\"POST\", \"/conversations\", {\n  participants: {\n    externals: [{\n      identifier: contactId,\n      identifierType: \"ID\",\n      messageProviderType: \"WHATSAPP\",\n      providerChannelId,\n    }],\n    internals: [{ identifier: internalEmail, identifierType: \"EMAIL\" }],\n  },\n  onboardingTemplates: [{ templateId: template.id, parameters }],\n}, 201);\nif (!conversation?.id || conversation.workspaceId !== workspaceId) {\n  throw new Error(\"The Conversation response does not identify the intended workspace.\");\n}\nconsole.log({ templateId: template.id, conversationId: conversation.id });\n```\n\n```bash\nnode send-template.mjs\n```\n\nO exemplo usa o ID retornado pela descoberta em `onboardingTemplates[].templateId`. As duas operações outbound também aceitam ID ou nome do template, com prioridade para o ID quando ambos são informados. Seus formatos de requisição são diferentes de `onboardingTemplates`; leia o contrato da operação antes de reutilizar esse corpo em outro contexto.\n\nAs verificações locais detectam chaves desconhecidas ou obrigatórias ausentes. O Bridge ainda realiza sua própria validação, incluindo a aprovação para a linha selecionada e as regras finais de valores do WhatsApp. Não trate a validação local como aprovação ou garantia de entrega.\n\n## Corrija uma requisição rejeitada\n\n| Erro | O que fazer |\n| --- | --- |\n| Descoberta `BRIDGE_TEMPLATE_0001` | Confira o ID ou nome e o workspace. Essa resposta não revela se o identificador pertence a outro workspace. |\n| `BRIDGE_CONVERSATION_0604` | Forneça valores não vazios para as variáveis de `extra.missingVariables`. |\n| `BRIDGE_CONVERSATION_0605` | Remova as chaves de `extra.unknownKeys`; use as chaves agnósticas da descoberta. |\n| `BRIDGE_CONVERSATION_0607` | Corrija os valores de `extra.invalidVariables` conforme o `reason` de cada um. |\n| `BRIDGE_CONVERSATION_0608` | Peça a um administrador do workspace para alterar a sequência inicial configurada. Mudar os valores do seu template não corrige esse erro de configuração. |\n\nLeia a [referência completa de erros de templates](https://docs.bridge.new/pt-br/templates-and-parameters.md#errors) para entender aprovação, titularidade, parâmetros não aceitos e requisições malformadas. Não repita automaticamente uma requisição de conversa que expirou: primeiro verifique o resultado.\n"
    },
    {
      "title": "Inicie uma conversa outbound com um Agente",
      "source": "https://docs.bridge.new/pt-br/guides/agent-outbound",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/agent-outbound.md",
      "description": "Escolha um Agente, envie um template inicial, entenda forceSend e a recuperação de conversas e solicite uma transferência LeadScout.",
      "kind": "page",
      "contentMarkdown": "Use outbound quando um Contato existente deve receber um template aprovado de WhatsApp e continuar a conversa com um Agente de IA. Para o fluxo geral de conversas, use [criar uma conversa](https://docs.bridge.new/pt-br/guides/first-conversation.md).\n\n## Escolha a operação\n\n| Objetivo | Operação | Como o Agente é selecionado |\n| --- | --- | --- |\n| Iniciar com um LeadScout ou Service Agent específico | `POST /bridge/api/v1/workspaces/{workspaceId}/agents/{agentId}/outbound` | Você fornece o ID do Agente obtido em `GET /agents`. |\n| Iniciar com um LeadScout selecionado pelas linhas elegíveis do workspace | `POST /bridge/api/v1/workspaces/{workspaceId}/leadscout/outbound` | O Bridge identifica o Agente de prospecção da linha. |\n\nAs duas operações usam o host REST `https://api-connect-us.bridge.new` e `x-api-key` no servidor. Seus esquemas de requisição são separados. Leia a [referência de outbound de Agentes](https://docs.bridge.new/pt-br/api-reference/agents-api/iniciar-conversa-de-sa%C3%ADda-com-um-contact-como-agent-espec%C3%ADfico.md) ou a [referência de outbound de LeadScout](https://docs.bridge.new/pt-br/api-reference/leadscout-api/iniciar-conversa-de-sa%C3%ADda-do-leadscout-com-um-lead-conhecido.md), conforme a operação escolhida.\n\n## Antes de enviar\n\n1. [Consulte o Contato](https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador.md) ou [crie-o](https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-contato.md), se não existir. Outbound exige um Contato já existente no workspace; você não precisa criar antes uma conversa ou mensagem separada.\n2. [Liste os Agentes](https://docs.bridge.new/pt-br/api-reference/agents-api/listar-os-agents-de-um-workspace.md). Escolha um Agente disponível e leia seu `lines[].providerChannelId`. O ID de um Agente de IA é diferente do ID de um usuário humano do Bridge.\n3. Escolha um template aprovado. [Descubra suas variáveis](https://docs.bridge.new/pt-br/guides/send-template.md#1-discover-the-variables), forneça os valores exigidos do integrador e confirme a aprovação para a linha de destino. Use apenas a etapa de descoberta como pré-requisito: a etapa separada de criação de conversa desse guia não é necessária para outbound.\n4. Confirme que sua empresa tem o aceite necessário. Se enviar `consent.status: \"GRANTED\"`, inclua `capturedAt`; isso registra sua declaração de consentimento.\n\nNo outbound de Agentes, `contact.providerChannelId`, quando informado, deve pertencer ao Agente escolhido. Ele expressa uma preferência: outra linha elegível do Agente pode ser selecionada. No outbound de LeadScout, a linha explícita é respeitada. O guia de [identificadores e suas fontes](https://docs.bridge.new/pt-br/guides/identifiers.md) explica quais valores usar.\n\n## Envie uma requisição mínima de Agente\n\nSubstitua todos os valores de exemplo. Este caso pressupõe que o template escolhido não tenha variáveis obrigatórias do integrador ainda sem valor. Defina `forceSend` conscientemente; o exemplo mantém explícito o comportamento padrão.\n\n```bash\ncurl --fail-with-body --request POST \\\n  \"https://api-connect-us.bridge.new/bridge/api/v1/workspaces/$WORKSPACE_ID/agents/$AGENT_ID/outbound\" \\\n  --header \"x-api-key: $BRIDGE_API_KEY\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{\n    \"contact\": {\n      \"identifier\": \"f0000001-0000-4000-8000-000000000001\",\n      \"identifierType\": \"ID\",\n      \"messageProviderType\": \"WHATSAPP\"\n    },\n    \"template\": {\n      \"id\": \"f0000040-0000-4000-8000-000000000040\"\n    },\n    \"forceSend\": false\n  }'\n```\n\nUma requisição bem-sucedida retorna `201`. Guarde `conversation.id` e interprete os campos de resposta:\n\n| Campo | Significado |\n| --- | --- |\n| `alreadyInitiated: true` | Uma conversa ativa existente foi reutilizada. A requisição bem-sucedida ainda acrescenta seu novo template e as mensagens de acompanhamento. |\n| `recovered: true` | Uma conversa liberada e recuperável foi recuperada, mantendo o ID. O contexto outbound anterior e `agentContext` são substituídos. |\n| `additionalMessagesPersisted` | Quantidade de mensagens de acompanhamento armazenadas. Não é um comprovante de entrega. |\n| `templateSent` | Resumo do template inicial armazenado para envio. Não interprete o nome do campo como prova de entrega ao destinatário. |\n\nEm uma criação nova, os indicadores de reutilização e recuperação não são true. A recuperação pode ocorrer com `forceSend: false`. As mensagens adicionais são persistidas na ordem da requisição; não conte com uma promessa de que aguardam a resposta do Contato. O fluxo outbound compartilhado persiste mensagens de acompanhamento em texto e não anexa seus `mediaIds`. Use a opção documentada `template.media` para mídia no template inicial ou o [fluxo de anexos de mensagem](https://docs.bridge.new/pt-br/guides/send-attachments.md) para uma mensagem separada.\n\n## O que forceSend faz\n\nA disponibilidade é avaliada para **a conversa desse Contato em cada linha**. Uma linha ocupada, nesse contexto, não significa que a linha corporativa de WhatsApp esteja globalmente reservada a um único Contato.\n\nAs regras abaixo continuam sujeitas à disponibilidade do Agente, à validação do template e do consentimento e às verificações de sessão.\n\nEm telas estreitas, role horizontalmente para comparar as quatro opções. Quem usa o teclado pode colocar o foco nessa comparação e usar as teclas de seta.\n\n| Situação | LeadScout: false | LeadScout: true | Agentes: false | Agentes: true |\n| --- | --- | --- | --- | --- |\n| A linha selecionada está livre | Cria | Cria | Cria | Cria |\n| A linha selecionada contém uma conversa liberada marcada como recuperável | Recupera o mesmo ID | Recupera o mesmo ID | Recupera o mesmo ID | Recupera o mesmo ID |\n| A seleção automática encontra apenas conversas ativas ocupadas | `409 …0008` | Reutiliza a primeira conversa ocupada elegível | `409 …0008` | Prioriza uma conversa controlada pelo Agente solicitado e aplica a verificação de controlador abaixo |\n| A linha explícita está ocupada | `409 …0007` | Reutiliza essa conversa | Tenta outras linhas livres ou recuperáveis do Agente; se não houver, `409 …0008` | Tenta outras linhas livres ou recuperáveis; se não houver, prioriza uma linha ocupada controlada pelo Agente |\n| A conversa ocupada selecionada é controlada por uma pessoa ou outro Agente | Não reutiliza a conversa ativa | A rota legada permite reutilização, sujeita às demais verificações; isso não promete, por si só, transferência de controle | Não reutiliza a conversa ativa | `409 BRIDGE_AI_AGENT_OUTBOUND_0006`; essa rejeição não grava nada |\n| Há apenas conversas bloqueadas ou liberadas não recuperáveis | `409 …0008` | `409 …0008` | `409 …0008` | `409 …0008` |\n\nNesta tabela, `…0007` corresponde a `BRIDGE_AI_LEADSCOUT_0007`, e `…0008`, a `BRIDGE_AI_LEADSCOUT_0008`. Uma conversa liberada só é recuperável quando o sinalizador de recuperação armazenado permite; `forceSend` não a torna recuperável.\n\nNas duas rotas, uma sessão LeadScout ainda aberta e não expirada bloqueia uma nova requisição outbound com `409 BRIDGE_AI_LEADSCOUT_0017`. A falha ao finalizar uma sessão expirada retorna `409 BRIDGE_AI_LEADSCOUT_0018`. Um Service Agent pode continuar sua sessão de serviço aberta e não expirada; uma sessão expirada é encerrada antes de iniciar outra.\n\n**Aviso**\n\n  `forceSend` não é uma chave de idempotência. Repetir uma requisição bem-sucedida pode acrescentar outro template e mais mensagens. O sinalizador não ignora conversas bloqueadas, verificações de sessão, regras de aprovação ou validação. Um timeout deixa o resultado incerto: consulte a conversa antes de decidir reenviar.\n\n## Trate conflitos e trabalho parcial\n\n| Resultado | Próxima etapa |\n| --- | --- |\n| `BRIDGE_AI_LEADSCOUT_0007` / `0008` | Confira a conversa existente do Contato e as linhas elegíveis. Decida se a reutilização é apropriada antes de habilitar `forceSend`. |\n| `BRIDGE_AI_AGENT_OUTBOUND_0006` | Examine `extra.conversationId` e seu controlador. Combine a responsabilidade pelo atendimento antes de liberar a conversa de propósito. Não interrompa automaticamente uma conversa humana. |\n| `BRIDGE_AI_LEADSCOUT_0017` / `0018` | Resolva a sessão existente ou contate o suporte. Mudar `forceSend` para true não corrige a sessão. |\n| `BRIDGE_AI_LEADSCOUT_0019` / `0020` / `0021` | Corrija variáveis obrigatórias ausentes, conflitantes ou desconhecidas usando a descoberta. |\n| `400 BRIDGE_AI_LEADSCOUT_0016` para `mediaId` de template desconhecido no outbound de Agentes | A conversa pode já ter sido criada ou recuperada antes desse erro. Consulte-a antes de tentar novamente. |\n\n[Liberar conversa](https://docs.bridge.new/pt-br/api-reference/conversations-api/liberar-conversa.md) é uma operação separada, com efeitos de negócio. Uma resposta `204` não tem corpo. Libere a conversa somente quando encerrá-la for a ação desejada.\n\n## Solicite a transferência de LeadScout para uma pessoa\n\nPara uma conversa LeadScout, obtenha o [ID ou e-mail do usuário humano do Bridge](https://docs.bridge.new/pt-br/guides/identifiers.md) e chame o [endpoint de transferência manual](https://docs.bridge.new/pt-br/api-reference/leadscout-api/solicitar-transfer%C3%AAncia-manual-do-leadscout-para-usu%C3%A1rios-internos.md). Essa operação é específica de LeadScout; não presuma que também se aplica a um Service Agent.\n\n```bash\ncurl --fail-with-body --request POST \\\n  \"https://api-connect-us.bridge.new/bridge/api/v1/workspaces/$WORKSPACE_ID/leadscout/conversations/$CONVERSATION_ID/handoff\" \\\n  --header \"x-api-key: $BRIDGE_API_KEY\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{\n    \"assignees\": [\n      {\"identifier\": \"f0000002-0000-4000-8000-000000000002\", \"identifierType\": \"ID\"}\n    ]\n  }'\n```\n\nUma resposta `202` confirma a aceitação da solicitação. Guarde `trackingId` e `conversationId`; a aceitação não comprova que a atribuição terminou nem que uma pessoa leu ou respondeu à conversa. A referência não publica um endpoint de acompanhamento da transferência, portanto não construa um a partir de `trackingId`.\n\nContinue com o [tratamento de erros](https://docs.bridge.new/pt-br/error-codes.md) e o [recebimento de webhooks](https://docs.bridge.new/pt-br/webhooks/receive-events.md) para conectar esse fluxo ao seu sistema.\n"
    },
    {
      "title": "Leia todas as páginas de resultados",
      "source": "https://docs.bridge.new/pt-br/guides/pagination",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/pagination.md",
      "description": "Percorra os cursores opacos de Contatos, conversas, usuários do Bridge e Agentes, sem parar em uma página com poucos registros.",
      "kind": "page",
      "contentMarkdown": "Os endpoints de listagem retornam uma coleção e um `cursor` opcional. Envie esse cursor sem alterações para ler a próxima página. Continue seguindo os cursores até que o valor seja nulo ou esteja ausente.\n\n## Escolha a coleção\n\nOs quatro endpoints abaixo aceitam `limit` de **1 a 100**, com valor padrão **20**.\n\n| Recurso | Caminho após o workspace | Campo da coleção |\n| --- | --- | --- |\n| Contatos | `/contacts` | `contacts` |\n| Conversas | `/conversations` | `conversations` |\n| Usuários do Bridge | `/users` | `users` |\n| Agentes | `/agents` | `agents` |\n\nUse a [consulta de contatos](https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador.md) ou a [consulta de usuários do Bridge](https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-um-identificador.md) quando precisar encontrar uma pessoa conhecida. Percorrer a lista inteira é uma tarefa diferente.\n\n## Exemplo no servidor\n\nEste exemplo lê Contatos. Salve como `list-contacts.mjs` e defina `BRIDGE_API_KEY` e `BRIDGE_WORKSPACE_ID` no servidor.\n\nA proteção local `maxPages` evita uma execução ilimitada por engano; ela não é um limite da API Bridge. A proteção contra cursores repetidos interrompe a execução e informa o problema, em vez de retornar silenciosamente uma lista incompleta.\n\n```javascript\nconst BASE = \"https://api-connect-us.bridge.new\";\nconst apiKey = process.env.BRIDGE_API_KEY;\nconst workspaceId = process.env.BRIDGE_WORKSPACE_ID;\nif (!apiKey || !workspaceId) {\n  throw new Error(\"Set BRIDGE_API_KEY and BRIDGE_WORKSPACE_ID.\");\n}\n\nasync function* pages(resource, collection, filters = {}) {\n  let cursor;\n  const seen = new Set();\n  const maxPages = 10000;\n\n  for (let pageNumber = 0; pageNumber < maxPages; pageNumber += 1) {\n    const url = new URL(\n      `/bridge/api/v1/workspaces/${encodeURIComponent(workspaceId)}/${resource}`,\n      BASE,\n    );\n    for (const [key, value] of Object.entries(filters)) {\n      url.searchParams.set(key, String(value));\n    }\n    url.searchParams.set(\"limit\", \"100\");\n    if (cursor !== undefined) url.searchParams.set(\"cursor\", cursor);\n\n    const response = await fetch(url, { headers: { \"x-api-key\": apiKey } });\n    const body = await response.json().catch(() => null);\n    if (response.status !== 200) {\n      const code = body?.code ? ` (${body.code})` : \"\";\n      throw new Error(`List ${resource}: HTTP ${response.status}${code}`);\n    }\n    if (!Array.isArray(body?.[collection])) {\n      throw new Error(`Expected the ${collection} collection.`);\n    }\n\n    yield body[collection];\n    if (body.cursor === null || body.cursor === undefined) return;\n    if (typeof body.cursor !== \"string\" || seen.has(body.cursor)) {\n      throw new Error(\"Invalid or repeated cursor; stopped without claiming completion.\");\n    }\n    seen.add(body.cursor);\n    cursor = body.cursor;\n  }\n  throw new Error(\"Local page guard reached; the sweep is incomplete.\");\n}\n\nlet count = 0;\nfor await (const contacts of pages(\"contacts\", \"contacts\")) {\n  // Process or store this page before continuing. Avoid logging personal data.\n  count += contacts.length;\n}\nconsole.log({ contactsRead: count });\n```\n\n```bash\nnode list-contacts.mjs\n```\n\nUse `pages(\"conversations\", \"conversations\", { status: \"ACTIVE\" })`, `pages(\"users\", \"users\")` ou `pages(\"agents\", \"agents\")` com o contrato correspondente. Mantenha os mesmos filtros durante todo o percurso.\n\n## Não pare em uma página com poucos registros\n\nUma página com menos registros que `limit` ainda pode ter uma próxima página. O endpoint de Agentes documenta esse comportamento explicitamente. O sinal de continuação é o cursor retornado, não o tamanho da coleção.\n\nTrate o cursor como opaco. Não o decodifique, incremente ou crie por conta própria. O `URL.searchParams` do exemplo preserva seu valor por meio da codificação de URL.\n\n## Filtros e limites de requisições\n\n- Os filtros `ownerEmail` e `search` da lista de Contatos estão obsoletos. Para um e-mail ou telefone conhecido, use a consulta de contatos. Para filtrar um conjunto por `ownerId`, leia esse campo nas linhas retornadas e faça a filtragem no seu código.\n- Os filtros `email` e `status` da lista de usuários do Bridge estão obsoletos. Use a consulta para um e-mail conhecido ou examine o `status` de cada usuário retornado.\n- Cada requisição de página consome a cota compartilhada do workspace. Siga o guia de [limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md), incluindo `Retry-After` em respostas `429`. Este exemplo mínimo para em respostas diferentes de 200, sem tentar novamente automaticamente.\n\nOs contratos publicados não garantem uma visão transacionalmente consistente da lista enquanto os registros estão mudando. Não apresente esse percurso como uma exportação necessariamente consistente nem presuma um prazo de validade do cursor que não esteja documentado.\n\n## Referências\n\n- [Listar Contatos](https://docs.bridge.new/pt-br/api-reference/contacts-api/listar-contatos.md)\n- [Listar conversas](https://docs.bridge.new/pt-br/api-reference/conversations-api/consultar-conversas-com-filtros-flex%C3%ADveis.md)\n- [Listar usuários do Bridge](https://docs.bridge.new/pt-br/api-reference/internal-users-api/listar-usu%C3%A1rios-internos.md)\n- [Listar Agentes](https://docs.bridge.new/pt-br/api-reference/agents-api/listar-os-agents-de-um-workspace.md)\n- [Respostas e erros](https://docs.bridge.new/pt-br/guides/responses.md)\n"
    },
    {
      "title": "Respostas, erros e novas tentativas",
      "source": "https://docs.bridge.new/pt-br/guides/responses",
      "markdownUrl": "https://docs.bridge.new/pt-br/guides/responses.md",
      "description": "Interprete criação, aceitação, respostas vazias, erros de validação e sinais de nova tentativa, sem confundir os contratos REST e de Custom Connections.",
      "kind": "page",
      "contentMarkdown": "## Interprete o resultado da operação\n\nO status HTTP e o corpo da resposta descrevem a operação chamada. Eles nem sempre significam que uma pessoa recebeu uma mensagem.\n\n| Operação | Sucesso publicado | O que fazer com o resultado |\n| --- | --- | --- |\n| Criar uma mensagem | `201`, com `messageId` | Guarde o ID da mensagem. A resposta publicada não inclui um comprovante de entrega do provedor; não a apresente como entregue com base apenas nessa resposta. |\n| Liberar uma conversa | `204`, sem corpo de resposta | Trate como sucesso e não chame um parser de JSON para o corpo vazio. |\n| Solicitar transferência LeadScout | `202`, com `trackingId`, `conversationId`, `status` e `assignees` | Guarde o ID de correlação. A atribuição é assíncrona; os destinatários repetem o que foi solicitado e não comprovam que a resolução ou atribuição posterior terminou. |\n| Enviar um lead por Custom Connections | `202`, com `requestId` | Guarde o ID da requisição. Informe que o lead foi aceito; a mensagem inicial de WhatsApp é enviada depois por um serviço separado. |\n\nA referência de cada operação continua sendo a fonte do contrato: [mensagens](https://docs.bridge.new/pt-br/api-reference/messages-api/criar-mensagem.md), [liberação](https://docs.bridge.new/pt-br/api-reference/conversations-api/liberar-conversa.md), [transferência](https://docs.bridge.new/pt-br/api-reference/leadscout-api/solicitar-transfer%C3%AAncia-manual-do-leadscout-para-usu%C3%A1rios-internos.md) e [Custom Connections](https://docs.bridge.new/pt-br/api-reference/campaign-leads/registrar-um-lead-de-campanha.md).\n\n**Nota**\n\n  Um ID de correlação não é uma URL de consulta de status. O contrato publicado não define um endpoint de consulta periódica para `trackingId` ou `requestId`. Guarde-o para correlação e suporte; não construa um novo endpoint a partir dele.\n\n## Leia o formato de erro publicado pelo endpoint\n\nA API REST de integrações e Custom Connections têm contratos de erro separados.\n\n### API REST de integrações\n\nMuitas respostas usam `Problem`: `title` e `status` são obrigatórios; `code`, `detail`, `errors`, `traceId`, `instance` e `extra` são opcionais. Quando `code` estiver presente, use-o para selecionar o tratamento de erro documentado, em vez de comparar o texto de `title`. Guarde `traceId`, quando fornecido, para pedir suporte.\n\nAlgumas respostas de validação publicadas declaram `HTTPValidationError`, cujo `detail` é um array de entradas com `loc`, `msg` e `type`. Já o tratador compartilhado de erros da API revisado para esta documentação retorna os detalhes de validação em `Problem.errors[]`. As definições publicadas de resposta foram preservadas; a confirmação na API implantada ainda está pendente. Veja a [nota de compatibilidade de validação](https://docs.bridge.new/pt-br/error-codes.md#parse-validation-errors-defensively).\n\nAceite erros JSON tanto com `application/json` quanto com `application/problem+json`. Examine `code`, quando presente, e depois um array `errors` ou `detail` para os erros de campo. Um `detail` do tipo string é uma explicação, não um array. O status `422` sozinho não define um formato universal de corpo. Mantenha um tratamento alternativo para erros sem `code` e use a referência do endpoint junto com [códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) para escolher a ação.\n\n### Custom Connections\n\nSeu corpo de erro contém `type`, `title` e `status` obrigatórios e pode incluir `detail`. Nesse contrato, **`type` é o identificador de erro legível por máquina**. Ele não é o campo REST `code`. A [referência de erros de Custom Connections](https://docs.bridge.new/pt-br/lead-capture/errors.md) lista essas respostas.\n\nAs respostas de erro não contêm o `requestId` do envio; somente uma resposta bem-sucedida `202` contém esse valor. Para pedir suporte sobre um erro, guarde a URL da página e o horário aproximado, conforme a referência.\n\n## Decida se deve tentar novamente por operação e causa\n\n| Resultado | Próxima ação |\n| --- | --- |\n| REST `429` | Siga `Retry-After` em segundos. O guia de limites informa que a requisição rejeitada não foi processada. A cota do workspace é compartilhada entre as chaves de API. |\n| REST `401` ou `403` | Corrija a chave de API, as permissões ou a divergência de workspace. Tentar novamente após um intervalo não corrige essas causas. |\n| Erro de validação ou configuração | Corrija primeiro a causa documentada. Não envie repetidamente a mesma requisição inválida. |\n| Custom Connections `422` | A causa documentada é a indisponibilidade do provedor de CAPTCHA. O guia de erros informa que é seguro tentar novamente; gere um novo token de CAPTCHA para a tentativa. |\n| Rejeição de CAPTCHA em Custom Connections | Confira se o token foi enviado, se é recente e se foi gerado para essa tentativa. O mesmo erro também abrange uma pontuação baixa; uma nova tentativa, sozinha, não comprova a causa original. |\n| Timeout, perda de conexão ou `5xx` não classificado durante uma alteração | Não presuma que nada aconteceu. Verifique os efeitos documentados da operação e os identificadores já obtidos antes de decidir repeti-la. Não presuma uma garantia geral de idempotência. |\n\nVeja [limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md) para controlar o ritmo e [erros de Custom Connections](https://docs.bridge.new/pt-br/lead-capture/errors.md) para suas regras específicas de nova tentativa.\n\n## Algumas falhas podem ocorrer depois de uma gravação\n\nA [referência de outbound de Agente](https://docs.bridge.new/pt-br/api-reference/agents-api/iniciar-conversa-de-sa%C3%ADda-com-um-contact-como-agent-espec%C3%ADfico.md) documenta que um `template.media.mediaId` desconhecido pode produzir `BRIDGE_AI_LEADSCOUT_0016` depois que a conversa já foi criada ou recuperada. Por isso, uma nova tentativa pode produzir um resultado diferente.\n\nUm status de falha, portanto, não é uma garantia universal de rollback. Siga os efeitos e as instruções de recuperação da operação específica. Se essas instruções forem pouco claras ou conflitantes, identifique a incerteza e entre em contato com o [suporte do Bridge](mailto:support@sainapsis.com) antes de repetir uma ação com efeitos externos.\n"
    },
    {
      "title": "Parâmetros de templates de WhatsApp",
      "source": "https://docs.bridge.new/pt-br/templates-and-parameters",
      "markdownUrl": "https://docs.bridge.new/pt-br/templates-and-parameters.md",
      "description": "Abra uma conversa com seus próprios templates de WhatsApp, preencha as variáveis e trate os erros que a requisição pode retornar.",
      "kind": "page",
      "contentMarkdown": "## Visão geral\n\nAo criar uma conversa, `onboardingTemplates` permite escolher, em ordem, os templates de WhatsApp usados na abertura. Um template pode conter variáveis, como número de pedido, data de entrega ou nome do Contato. O Bridge preenche algumas delas para cada Contato; outras só você pode fornecer, enviando-as em `parameters` da entrada correspondente.\n\nO fluxo tem três etapas:\n\n1. Consulte as variáveis do template.\n2. Decida quais valores enviar.\n3. Envie-os com `POST .../conversations`.\n\n**Nota**\n\n  Todas as verificações descritas nesta página ocorrem antes de qualquer criação. Se a requisição for rejeitada, **nenhuma conversa é criada e nenhuma mensagem é enviada**. Você pode corrigi-la e enviá-la novamente.\n\n---\n\n## 1. Encontre as variáveis do template\n\n```http\nGET /bridge/api/v1/workspaces/{workspaceId}/templates/{templateId}\nx-api-key: YOUR_API_KEY\n```\n\n`templateId` aceita o `id` ou o `name` do template. A resposta lista suas variáveis:\n\n```json\n{\n  \"id\": \"f0000040-0000-4000-8000-000000000040\",\n  \"name\": \"order_shipped_promo\",\n  \"language\": \"es\",\n  \"driftWarning\": { \"hasDrift\": false, \"stale\": [], \"missingLabels\": [] },\n  \"variables\": [\n    { \"key\": \"first_name\", \"label\": \"Contact first name\", \"callerMustSupply\": false, \"isCustom\": false, \"default\": null },\n    { \"key\": \"order_number\", \"label\": \"Order number\", \"callerMustSupply\": true, \"isCustom\": false, \"default\": null },\n    { \"key\": \"delivery_date\", \"label\": \"Delivery date\", \"callerMustSupply\": true, \"isCustom\": false, \"default\": null },\n    { \"key\": \"tracking_code\", \"label\": \"Tracking code\", \"callerMustSupply\": false, \"isCustom\": true, \"default\": \"pending\" }\n  ]\n}\n```\n\n`driftWarning` é apenas diagnóstico: informa diferenças entre as variáveis declaradas e o snapshot do template na Meta e nunca bloqueia um envio. A tabela abaixo descreve cada item de `variables`.\n\n| Campo | Significado |\n| ----- | ------- |\n| `key` | O nome a usar em `parameters` |\n| `label` | Uma descrição da variável legível por pessoas |\n| `callerMustSupply` | `true` quando você precisa fornecer um valor não vazio porque o Bridge não tem uma fonte para ele; `false` nos demais casos |\n| `isCustom` | Indica se a variável é personalizada: um valor que só você conhece, com um texto padrão |\n| `default` | Para uma variável personalizada, o texto enviado quando você não fornece um valor; `null` nos demais casos |\n\nUm template que não pertence ao workspace retorna `404` com `BRIDGE_TEMPLATE_0001`.\n\n---\n\n## 2. Decida quais valores enviar\n\n| Variável | O que significa | O que fazer |\n| -------- | ------------- | ---------- |\n| `callerMustSupply: true` | O Bridge não tem uma fonte para esse valor | **Obrigatório.** Envie um valor não vazio para sua `key` |\n| `callerMustSupply: false`, `isCustom: false` | O Bridge preenche o valor para cada Contato, como o primeiro nome | **Opcional.** Omita-o para manter o valor do Bridge |\n| `isCustom: true` | Um valor que só você conhece, com um `default` | **Opcional.** Envie seu valor, omita-o ou envie-o vazio para usar o `default` |\n\nUm valor enviado para uma variável `callerMustSupply: false` substitui o valor do Bridge e é usado **para todos os Contatos** da conversa.\n\n**Aviso**\n\n  Para uma variável não personalizada, mantenha o valor do Bridge **omitindo a chave**. Um valor vazio não significa \"usar o padrão\": ele é enviado como você o escreveu. Uma variável obrigatória vazia ou composta apenas de espaços é rejeitada como ausente. Somente variáveis personalizadas (`isCustom: true`) tratam um valor vazio como não enviado e usam seu `default`.\n\n---\n\n## 3. Envie os parâmetros\n\nCada entrada de `onboardingTemplates` recebe o `id` do template retornado na etapa 1 e seus `parameters`, indexados pela `key` da variável. A posição na lista define a ordem de envio.\n\n```http\nPOST /bridge/api/v1/workspaces/{workspaceId}/conversations\nx-api-key: YOUR_API_KEY\nContent-Type: application/json\n```\n\n```json\n{\n  \"participants\": {\n    \"externals\": [\n      {\n        \"identifier\": \"+13802098869\",\n        \"identifierType\": \"PHONE\",\n        \"messageProviderType\": \"WHATSAPP\",\n        \"brandId\": \"YOUR_BRAND_ID\"\n      }\n    ]\n  },\n  \"onboardingTemplates\": [\n    {\n      \"templateId\": \"f0000040-0000-4000-8000-000000000040\",\n      \"parameters\": {\n        \"order_number\": \"A-10492\",\n        \"delivery_date\": \"3 de octubre\"\n      }\n    }\n  ]\n}\n```\n\nNeste exemplo, `first_name` e `tracking_code` são omitidos. Assim, cada Contato recebe seu próprio primeiro nome, e `tracking_code` é enviado com seu valor padrão, `pending`.\n\nLimites por template: no máximo **50** parâmetros, chaves de até **128** caracteres e valores de até **1.024** caracteres. Requisições que ultrapassam esses limites são rejeitadas como malformadas; veja [erros](https://docs.bridge.new/pt-br/templates-and-parameters.md#errors).\n\nConforme a configuração do workspace, seus templates substituem toda a sequência inicial ou apenas o primeiro template. No segundo caso, o restante da sequência configurada ainda é enviado depois dos seus.\n\n---\n\n## Regras de valores do WhatsApp\n\nO WhatsApp rejeita determinados valores no envio da mensagem. O Bridge os verifica antes para que a requisição falhe enquanto você ainda pode corrigi-los:\n\n| Regra | Limite |\n| ---- | ----- |\n| Quebras de linha e tabulações | Não permitidas: sem `\\n`, `\\r` ou `\\t` |\n| Espaços consecutivos | No máximo quatro seguidos |\n| Cabeçalho | O texto do cabeçalho com o valor inserido deve caber em **60** caracteres |\n| Botão de URL | O link do botão com o valor inserido deve caber em **2.000** caracteres |\n| Corpo | O texto do corpo mais todos os valores deve caber em **1.024** caracteres |\n\n**Aviso**\n\n  O limite do corpo inclui os valores que o Bridge preenche para cada Contato, como o primeiro nome. O Bridge só consegue verificar os valores disponíveis no momento da requisição; reserve espaço para os demais.\n\nO Bridge nunca remove espaços das extremidades nem reescreve seus valores: o que você envia é o que o Contato recebe.\n\n---\n\n## Erros\n\nTodos os erros usam o formato `application/problem+json` descrito em [códigos de erro](https://docs.bridge.new/pt-br/error-codes.md). Escolha o tratamento por `code`, nunca por `title`.\n\n| Código | Status | Quando ocorre | `extra` |\n| ---- | ------ | ---- | ------- |\n| `BRIDGE_CONVERSATION_0601` | 404 | O template não existe | `templateId`, `workspaceId` |\n| `BRIDGE_CONVERSATION_0602` | 400 | O template pertence a outro workspace | `templateId`, `workspaceId` |\n| `BRIDGE_CONVERSATION_0603` | 400 | O template não foi aprovado para a linha pela qual um participante será contatado | `templateId`, `workspaceId`, `userIds` (os Contatos cuja linha não tem aprovação, quando conhecidos) |\n| `BRIDGE_CONVERSATION_0604` | 422 | Uma variável obrigatória está ausente ou vazia | `templateId`, `missingVariables: [{key, label}]` |\n| `BRIDGE_CONVERSATION_0605` | 422 | Uma chave de `parameters` não está entre as variáveis do template | `templateId`, `unknownKeys: [key]` |\n| `BRIDGE_CONVERSATION_0606` | 422 | `parameters` foi enviado para um template que não é de WhatsApp | `templateId` |\n| `BRIDGE_CONVERSATION_0607` | 422 | Um valor viola uma [regra do WhatsApp](https://docs.bridge.new/pt-br/templates-and-parameters.md#whatsapp-value-rules) | `templateId`, `invalidVariables: [{key, label, reason}]` |\n| `BRIDGE_CONVERSATION_0608` | 422 | Um template enviado pelo workspace depois do seu exige valores que só o integrador pode fornecer | `templateId`, `origin: \"WORKSPACE_CONFIGURATION\"` |\n\n### Valores ausentes — `0604`\n\n```json\n{\n  \"title\": \"A template named in the onboarding override is missing values only the caller can provide\",\n  \"status\": 422,\n  \"detail\": \"A template named in the onboarding override is missing values only the caller can provide\",\n  \"code\": \"BRIDGE_CONVERSATION_0604\",\n  \"extra\": {\n    \"templateId\": \"f0000040-0000-4000-8000-000000000040\",\n    \"missingVariables\": [\n      { \"key\": \"delivery_date\", \"label\": \"Delivery date\" }\n    ]\n  }\n}\n```\n\n\n### Valores inválidos — `0607`\n\n```json\n{\n  \"title\": \"Parameter values for an onboarding template break a WhatsApp rule and would be rejected when sent\",\n  \"status\": 422,\n  \"detail\": \"Parameter values for an onboarding template break a WhatsApp rule and would be rejected when sent\",\n  \"code\": \"BRIDGE_CONVERSATION_0607\",\n  \"extra\": {\n    \"templateId\": \"f0000040-0000-4000-8000-000000000040\",\n    \"invalidVariables\": [\n      { \"key\": \"order_number\", \"label\": \"Order number\", \"reason\": \"NEWLINE\" }\n    ]\n  }\n}\n```\n\n`reason` informa a primeira regra violada pelo valor:\n\n| `reason` | Significado |\n| -------- | ------- |\n| `NEWLINE` | O valor contém `\\n` ou `\\r` |\n| `TAB` | O valor contém `\\t` |\n| `CONSECUTIVE_SPACES` | O valor contém mais de quatro espaços seguidos |\n| `TOO_LONG` | O cabeçalho ou botão de URL ultrapassa o limite com o valor inserido |\n| `BODY_TOO_LONG` | O corpo ultrapassa 1.024 caracteres; todos os valores de corpo enviados são listados |\n\n### O erro `0608` não se resolve alterando a requisição\n\n`BRIDGE_CONVERSATION_0608` ocorre somente em workspaces em que seus templates substituem apenas o primeiro template da sequência inicial. Isso significa que um template enviado pelo workspace depois do seu precisa de valores que só o integrador pode fornecer e que a API não consegue suprir. Peça a um administrador para alterar a sequência inicial.\n\n### Requisições malformadas\n\nUma requisição incompatível com o esquema — mais de 50 parâmetros, chave com mais de 128 caracteres, valor com mais de 1.024 caracteres ou campo desconhecido — é rejeitada com `422` **sem `code`**. Nesse caso, uma lista `errors` aponta cada problema:\n\n```json\n{\n  \"title\": \"Unprocessable content\",\n  \"status\": 422,\n  \"errors\": [\n    {\n      \"loc\": [\"body\", \"onboardingTemplates\", 0, \"parameters\", \"order_number\"],\n      \"msg\": \"String should have at most 1024 characters\",\n      \"type\": \"string_too_long\"\n    }\n  ]\n}\n```\n\n\n### Ordem de avaliação\n\nAs verificações seguem esta ordem, e **o primeiro erro prevalece**:\n\n1. Limite de requisições — `429`\n2. Formato da requisição — `422` sem `code`\n3. Participantes, marca e linha — `400` / `409`, por exemplo, `BRIDGE_BRAND_0101` ou `BRIDGE_PROVIDER_CHANNEL_0001`\n4. Cada template, na ordem da lista: `0601` / `0602` → `0603` → `0606` → `0605` → `0604` → `0607`\n5. `0608`, somente em workspaces onde seus templates substituem apenas o primeiro template\n\nPor isso, corrigir um erro pode revelar o próximo. Os valores de um template posterior só são verificados depois que todos os anteriores passam.\n\n---\n\n## Tópicos relacionados\n\n- [Criar uma conversa](https://docs.bridge.new/pt-br/api-reference/conversations-api/criar-conversa-com-identifica%C3%A7%C3%A3o-flex%C3%ADvel-de-usu%C3%A1rios.md) — Referência completa da requisição e resposta\n- [Códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) — Todos os códigos, incluindo erros de marca e linha\n- [Limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md) — Tratamento de `429`\n"
    },
    {
      "title": "Limites de requisições",
      "source": "https://docs.bridge.new/pt-br/rate-limits",
      "markdownUrl": "https://docs.bridge.new/pt-br/rate-limits.md",
      "description": "Quantas requisições a API Bridge aceita, quais cabeçalhos mostram a cota disponível e como tratar corretamente uma resposta 429.",
      "kind": "page",
      "contentMarkdown": "## Visão geral\n\nA API Bridge aceita **50 requisições a cada 5 segundos**. O limite se aplica a todos os endpoints, está habilitado por padrão e não exige configuração.\n\n**Nota**\n\n  A cota pertence ao **workspace**, não à chave de API. Se você emitir várias chaves para o mesmo workspace, uma por aplicação, como recomendado, todas compartilharão as mesmas 50 requisições.\n\n---\n\n## Consulte a cota disponível\n\nToda resposta a uma requisição autenticada contém dois cabeçalhos, para que você saiba quanto ainda pode usar:\n\n```http\nRateLimit-Policy: \"default\";q=50;w=5\nRateLimit: \"default\";r=43;t=3\n```\n\n| Campo | Significado |\n| ----- | ------- |\n| `q` | Requisições permitidas por janela |\n| `w` | Duração da janela em segundos |\n| `r` | Requisições **restantes** na janela atual |\n| `t` | Segundos até a janela reiniciar e `r` voltar a `q` |\n\nUm cliente que monitora `r` e pausa quando o valor se aproxima de zero evita rejeições por limite.\n\n**Nota**\n\n  Uma requisição rejeitada **antes** da autenticação, por chave de API ausente ou inválida, não contém esses cabeçalhos. Veja essas respostas em [autenticação](https://docs.bridge.new/pt-br/credentials.md).\n\n---\n\n## Quando o limite é excedido\n\nAs requisições acima da cota recebem `429 Too Many Requests`. Nada é processado, portanto é seguro repetir a requisição.\n\n```http\nHTTP/1.1 429 Too Many Requests\nContent-Type: application/problem+json\nRetry-After: 3\nRateLimit-Policy: \"default\";q=50;w=5\nRateLimit: \"default\";r=0;t=3\n```\n\n```json\n{\n  \"title\": \"Too Many Requests\",\n  \"status\": 429,\n  \"detail\": \"The workspace has exhausted its request budget for the current window\",\n  \"code\": \"BRIDGE_RATE_LIMIT_0001\"\n}\n```\n\n`Retry-After` é expresso em **segundos a partir de agora**, não como uma data. Aguarde esse intervalo antes de fazer a próxima requisição.\n\n**Aviso**\n\n  **Um `429` não é um problema de autenticação.** `401` e `403` significam que a chave de API está ausente, inválida, expirada ou sem autorização. **Repeti-los em intervalos não resolverá o problema** e apenas consumirá sua cota. Somente `429` deve ser repetido automaticamente, e apenas depois do intervalo informado.\n\n---\n\n## O que consome a cota\n\nCada requisição HTTP conta como uma, inclusive as que terminam em erro de validação ou `404`. O que importa é quantas chamadas o cliente faz, não a quantidade de dados retornados.\n\nEssa diferença aparece nas leituras:\n\n- **Um único recurso por ID** — `GET .../contacts/{contactId}` — custa **uma requisição**, independentemente do tamanho da resposta.\n- **Uma lista** — `GET .../contacts` — custa **uma requisição por página**. Ler a lista inteira custa tantas requisições quantas forem suas páginas.\n\nPor isso, o tamanho da página determina o custo de uma leitura completa. Percorrer 500 contatos custa cinco requisições com 100 por página e 25 requisições com 20 por página: os mesmos dados, com cinco vezes mais consumo de cota.\n\n**Nota**\n\n  Prefira o maior tamanho de página aceito pelo endpoint quando precisar ler a lista inteira. Se já souber qual recurso procura, leia-o diretamente pelo ID.\n\n---\n\n## Controle o ritmo na prática\n\nUm cliente que ajusta o ritmo com `RateLimit` e respeita `Retry-After` nas eventuais rejeições não precisa de outra lógica:\n\n```python\nimport time\n\nimport requests\n\nBASE = \"https://api-connect-us.bridge.new\"\nHEADERS = {\"x-api-key\": \"YOUR_API_KEY\"}\n\n\ndef rate_limit_state(response):\n    header = response.headers.get(\"RateLimit\", \"\")\n    fields = dict(part.split(\"=\", 1) for part in header.split(\";\") if \"=\" in part)\n    return int(fields.get(\"r\", 1)), int(fields.get(\"t\", 1))\n\n\ndef get(path):\n    while True:\n        response = requests.get(f\"{BASE}{path}\", headers=HEADERS)\n\n        if response.status_code == 429:\n            time.sleep(int(response.headers[\"Retry-After\"]))\n            continue\n\n        remaining, reset_in = rate_limit_state(response)\n        if remaining == 0:\n            time.sleep(reset_in)\n\n        return response\n```\n\n```javascript\nconst BASE = \"https://api-connect-us.bridge.new\";\nconst HEADERS = { \"x-api-key\": \"YOUR_API_KEY\" };\n\nconst sleep = (seconds) => new Promise((done) => setTimeout(done, seconds * 1000));\n\nfunction rateLimitState(response) {\n  const fields = Object.fromEntries(\n    (response.headers.get(\"RateLimit\") ?? \"\")\n      .split(\";\")\n      .filter((part) => part.includes(\"=\"))\n      .map((part) => part.split(\"=\"))\n  );\n  return { remaining: Number(fields.r ?? 1), resetIn: Number(fields.t ?? 1) };\n}\n\nasync function get(path) {\n  while (true) {\n    const response = await fetch(`${BASE}${path}`, { headers: HEADERS });\n\n    if (response.status === 429) {\n      await sleep(Number(response.headers.get(\"Retry-After\")));\n      continue;\n    }\n\n    const { remaining, resetIn } = rateLimitState(response);\n    if (remaining === 0) await sleep(resetIn);\n\n    return response;\n  }\n}\n```\n\n\n**Aviso**\n\n  Não repita um `429` imediatamente nem use um intervalo fixo definido por conta própria. Repetir antes de `Retry-After` terminar causa nova rejeição, e um loop intenso de tentativas mantém a cota do workspace em zero para todas as outras aplicações que a compartilham.\n\n---\n\n## Padrões\n\nEsses campos não são exclusivos do Bridge: `RateLimit-Policy` e `RateLimit` seguem a especificação IETF de [campos de cabeçalho RateLimit](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/); `Retry-After` segue a [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#field.retry-after); e o corpo do `429` segue a [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457.html). Se você já trata cabeçalhos `X-RateLimit-*` de outra API, esses são os equivalentes padronizados.\n\nQuando os dois divergirem, **`Retry-After` prevalece**: ele é o sinal que determina a nova tentativa, enquanto `RateLimit` orienta o ritmo das chamadas.\n\n---\n\n## Tópicos relacionados\n\n- [Autenticação](https://docs.bridge.new/pt-br/credentials.md) — Chaves de API e respostas `401` / `403` que não devem ser repetidas automaticamente\n- [Códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) — Referência completa, incluindo `BRIDGE_RATE_LIMIT_0001`\n- [Referência da API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md) — Cada endpoint documenta sua resposta `429`\n"
    },
    {
      "title": "Códigos de erro",
      "source": "https://docs.bridge.new/pt-br/error-codes",
      "markdownUrl": "https://docs.bridge.new/pt-br/error-codes.md",
      "description": "Interprete códigos de erro da API REST, respostas de validação e resultados incertos de gravações para escolher a próxima ação.",
      "kind": "page",
      "contentMarkdown": "## Formato da resposta\n\nExemplo de resposta `Problem`. Consulte na referência do endpoint o status HTTP, o tipo de mídia e o esquema da resposta:\n\n```json\n{\n  \"title\": \"A template named in the onboarding override is missing values only the caller can provide\",\n  \"status\": 422,\n  \"detail\": \"A template named in the onboarding override is missing values only the caller can provide\",\n  \"code\": \"BRIDGE_CONVERSATION_0604\",\n  \"extra\": {\n    \"templateId\": \"f0000040-0000-4000-8000-000000000040\",\n    \"missingVariables\": [{ \"key\": \"delivery_date\", \"label\": \"Delivery date\" }]\n  },\n  \"instance\": \"https://api-connect-us.bridge.new/bridge/api/v1/workspaces/{workspaceId}/conversations\",\n  \"traceId\": \"Root=1-6702b8c4-3f1a2b4c5d6e7f8091a2b3c4\"\n}\n```\n\n| Campo | Significado |\n| ----- | ------- |\n| `code` | Quando presente, o código estável de erro listado nesta página. **Escolha o tratamento por esse campo, não pelo título.** Erros de validação e de servidor podem omiti-lo. |\n| `title` | Uma mensagem legível por pessoas. Ela pode ser mais longa que o título das tabelas abaixo; nunca use seu texto para identificar o erro |\n| `status` | O código de status HTTP |\n| `detail` | Mais detalhes sobre a ocorrência, quando disponíveis |\n| `extra` | Contexto do erro legível por máquina, como IDs ou chaves envolvidos, quando disponível |\n| `instance` | A URL da requisição |\n| `traceId` | Inclua-o ao entrar em contato com o suporte |\n\n**Nota**\n\n  Leia o esquema de resposta da operação chamada. Quando ele for `HTTPValidationError`, os detalhes de validação estarão em um array `detail`; cada entrada contém `loc` (onde), `msg` (o quê) e `type`. Outras respostas `422` documentadas usam `Problem` e podem incluir `code` e `extra`. Não presuma que todas as respostas `422` tenham o mesmo formato.\n\n### Interprete erros de validação de forma defensiva\n\nAceite corpos de erro JSON tanto com `application/json` quanto com `application/problem+json`. Primeiro verifique o status HTTP; depois, examine o corpo:\n\n1. Se `code` estiver presente, use a entrada correspondente desta página para escolher a ação.\n2. Se `errors` for um array, leia suas entradas `loc`, `msg` e `type` como detalhes de validação.\n3. Se `detail` for um array, interprete-o no formato `HTTPValidationError`. Um `detail` do tipo string é uma explicação, não uma lista de erros de campo.\n4. Preserve `traceId`, o status e a URL da requisição para suporte. Não exija que `code` ou `extra` existam nem compare mensagens legíveis por pessoas como identificadores.\n\nUm campo inválido e uma regra que relaciona vários campos não precisam ter o mesmo status. As regras do corpo outbound revisadas geram `400` com `BRIDGE_CORE_0103` quando `consent.status` é `GRANTED` sem `capturedAt`, ou quando `template.media` fornece ambos ou nenhum de `mediaId` e `url`. Tipos de campo ou UUIDs inválidos podem gerar, por sua vez, detalhes de validação de requisição com `422`. Interprete o status e o corpo do erro juntos; não exija um array `errors` para toda requisição inválida.\n\n### Códigos legados com sufixo\n\nAlguns tratadores de erro legados acrescentam um nome simbólico a `code`, por exemplo, `BRIDGE_PRELOAD_FILE_0002 | PRELOAD_FILE_IS_PENDING`. Preserve o valor recebido completo para logs e suporte. Para consultar o catálogo, aceite um código simples conhecido ou sua forma legada reconhecida explicitamente; não compare `title` ou `detail`, não invente um código desconhecido nem reescreva o corpo da resposta. Esta revisão do código-fonte não confirmou de forma independente qual versão do tratador está implantada.\n\n**Aviso**\n\n  **Compatibilidade de validação:** algumas respostas OpenAPI publicadas declaram `HTTPValidationError.detail[]` e `application/json`, enquanto o tratador compartilhado de erros da API revisado para esta documentação retorna detalhes de validação como `Problem.errors[]` com `application/problem+json`. Esta atualização editorial preserva as definições de resposta publicadas. Trate os dois formatos; a confirmação na API implantada continua pendente antes de adotar um deles como único formato aceito por um cliente gerado estrito.\n\n### Decida se deve tentar novamente\n\n| Resultado | Ação |\n| --- | --- |\n| `400` ou `422` | Corrija a requisição usando o código e os erros de campo. Repetir os mesmos dados não corrige a validação. |\n| `401` ou `403` | Confira credencial, workspace e permissões da integração correta. Mantenha as chaves da API REST no servidor. |\n| `404` | Confirme o identificador e o workspace. Uma consulta que não encontra um Contato é diferente de uma entrada malformada. |\n| `409` | Leia o código da operação: conversa existente, Agente indisponível e sessão não finalizada exigem soluções diferentes. Não habilite `forceSend` automaticamente. |\n| `429` | Siga os [cabeçalhos de limite e as orientações de espera](https://docs.bridge.new/pt-br/rate-limits.md). |\n| Timeout, desconexão da resposta ou `5xx` após uma gravação | Trate o resultado como incerto. Consulte o recurso afetado antes de reenviar: um erro não comprova que nenhum trabalho foi persistido. |\n\nAs orientações gerais de nova tentativa não acrescentam idempotência a um endpoint. Para reutilização outbound, recuperação e gravações parciais, veja [outbound de Agente e transferência](https://docs.bridge.new/pt-br/guides/agent-outbound.md). Custom Connections tem sua própria [referência de erros](https://docs.bridge.new/pt-br/lead-capture/errors.md) e não usa chave da API REST.\n\n## Erros ao responder a uma mensagem\n\nPara `POST .../messages`, as verificações revisadas da mensagem à qual você responde definem estas formas legadas adicionais:\n\n- `BRIDGE_MESSAGE_0001 | MESSAGE_NOT_FOUND` (`404`): o Message indicado em `replyToMessageId` não foi encontrado.\n- `BRIDGE_MESSAGE_0002 | MESSAGE_IS_NOT_ON_CONVERSATION` (`403`): a mensagem à qual você responde pertence a outra Conversation. Use uma da Conversation em que você enviará a mensagem.\n\nPreserve o `code` completo, incluindo seu sufixo simbólico. Essas verificações se referem à mensagem à qual você responde, não ao `mediaId` do anexo.\n\n## Erros de upload de arquivos\n\nO fluxo de upload revisado define estes códigos legados. O sufixo faz parte do `code` recebido, não é um campo da requisição. Consulte o contrato de resposta da operação e mantenha a interpretação compatível acima.\n\nA operação determina quais erros de arquivo se aplicam: `POST .../files` verifica os metadados e pode retornar os códigos `0003` ou `0004` abaixo. `POST .../messages` pode retornar `0001` ou `0002` quando o `mediaId` de um anexo não existe ou ainda está pendente. Os arquivos de templates outbound têm seu próprio tratamento de erros; não substitua `BRIDGE_AI_LEADSCOUT_0016` por esses códigos.\n\n| `code` legado | Status | Ação |\n| --- | --- | --- |\n| `BRIDGE_PRELOAD_FILE_0001 \\| PRELOAD_FILE_NOT_FOUND` | 404 | Confira o `mediaId` retornado e o upload referenciado. |\n| `BRIDGE_PRELOAD_FILE_0002 \\| PRELOAD_FILE_IS_PENDING` | 400 | O arquivo ainda está pendente. Confirme que o PUT terminou e aguarde o processamento do upload; não conclua que uma requisição de Message com falha não persistiu nenhum trabalho. |\n| `BRIDGE_PRELOAD_FILE_0003 \\| PRELOAD_FILE_INVALID_MIME_TYPE` | 400 | Corrija a combinação do tipo MIME e do `fileType` lógico. |\n| `BRIDGE_PRELOAD_FILE_0004 \\| PRELOAD_FILE_INVALID_NAME` | 400 | Informe um nome com uma extensão aceita para esse `fileType` lógico. |\n\n## Códigos de erro de Agentes\n\nCódigos de erro de operações de Agentes.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_AI_AGENT_OUTBOUND_0001` | Agente não encontrado | O Agente não foi encontrado no workspace |\n| `BRIDGE_AI_AGENT_OUTBOUND_0002` | Agente indisponível | O Agente não está disponível para outbound |\n| `BRIDGE_AI_AGENT_OUTBOUND_0003` | Tipo de Agente não aceito | O tipo de Agente não é aceito para outbound |\n| `BRIDGE_AI_AGENT_OUTBOUND_0004` | Agente sem canais | Nenhuma linha ativa de mensagens está vinculada ao Agente |\n| `BRIDGE_AI_AGENT_OUTBOUND_0005` | Agente não atribuído ao canal | O Agente não está atribuído ao canal solicitado |\n| `BRIDGE_AI_AGENT_OUTBOUND_0006` | Conversa controlada por outro Agente | A conversa ativa é controlada por outro Agente |\n| `BRIDGE_AI_AGENT_OUTBOUND_0007` | Cursor inválido | O cursor de paginação está malformado ou pertence a outro workspace |\n\n`POST .../agents/{agentId}/outbound` retorna `0001` e `0004` como `404`, `0002` e `0006` como `409`, e `0003` e `0005` como `422`.\n\n- `0002`: o Agente é um rascunho ou não tem linha. `extra.reason` informa qual é o caso; o mesmo motivo aparece como `unavailableReason` em `GET .../agents`.\n- `0006`: a conversa do Contato na linha selecionada pela requisição está sob o controle de outro Agente ou de um usuário do Bridge. Nada foi enviado. Libere-a com `POST .../conversations/{conversationId}/release`, usando `extra.conversationId`, e depois tente novamente. `extra` também contém `channelId` e, somente quando o controlador é um Agente, `controllingAgentId`. Quando o controlador é um usuário do Bridge, a chave está ausente, não é `null`.\n\n`GET .../agents` retorna `0007` como `400` quando o `cursor` está malformado ou foi emitido para outro workspace. Recomece sem cursor. Mantenha o mesmo filtro `type` durante a paginação: um cursor emitido com um filtro `type` é rejeitado se a requisição informar outro `type`.\n\n### Outros códigos retornados por `POST .../agents/{agentId}/outbound`\n\n| Código | Status | Significado |\n| ---- | ------ | ------- |\n| `BRIDGE_CORE_0103` | 400 | A requisição é inválida: `consent.status` é `GRANTED` sem `capturedAt`, `template` não contém `id` nem `name`, ou `template.media` não contém exatamente um entre `mediaId` e `url` |\n| `BRIDGE_CORE_0301` | 403 | O workspace do caminho difere do workspace da chave de API |\n| `BRIDGE_AI_LEADSCOUT_0001` | 404 | O Contato não existe no workspace |\n| `BRIDGE_AI_LEADSCOUT_0002` | 404 | O usuário do Bridge de `handoffOverride` não existe no workspace |\n| `BRIDGE_AI_LEADSCOUT_0003` | 409 | O usuário do Bridge de `handoffOverride` foi excluído |\n| `BRIDGE_AI_LEADSCOUT_0004` | 404 | Nenhum template do workspace corresponde a `template.id` ou a `template.name`, quando nenhum ID é enviado |\n| `BRIDGE_AI_LEADSCOUT_0005` | 409 | Template não aprovado |\n| `BRIDGE_AI_LEADSCOUT_0006` | 400 | Os parâmetros ordenados do template não correspondem ao esperado |\n| `BRIDGE_AI_LEADSCOUT_0007` | 409 | Já existe uma conversa ativa: outra requisição assumiu primeiro a conversa liberada. Tente novamente |\n| `BRIDGE_AI_LEADSCOUT_0008` | 409 | Nenhuma linha do Agente está livre ou recuperável para esse Contato; veja `forceSend` |\n| `BRIDGE_AI_LEADSCOUT_0009` | 404 | Nenhuma linha configurada para o `brandId` solicitado |\n| `BRIDGE_AI_LEADSCOUT_0016` | 400 | Erro de validação outbound |\n| `BRIDGE_AI_LEADSCOUT_0017` | 409 | A sessão mais recente não foi finalizada |\n| `BRIDGE_AI_LEADSCOUT_0018` | 409 | Não foi possível finalizar a sessão expirada antes de iniciar uma nova |\n| `BRIDGE_AI_LEADSCOUT_0019` | 422 | Variáveis obrigatórias do template ausentes |\n| `BRIDGE_AI_LEADSCOUT_0020` | 422 | Fontes de parâmetros de template conflitantes para a mesma posição |\n| `BRIDGE_AI_LEADSCOUT_0021` | 422 | Chave de parâmetro de template desconhecida |\n\nEm `POST .../agents/{agentId}/outbound`, erros `5xx` não contêm `code` nem `extra`.\n\n## Códigos de erro de LeadScout\n\nCódigos adicionais documentados para [iniciar uma conversa outbound de LeadScout](https://docs.bridge.new/pt-br/api-reference/leadscout-api/iniciar-conversa-de-sa%C3%ADda-do-leadscout-com-um-lead-conhecido.md) com `POST .../leadscout/outbound`:\n\n| Código | Status | Título | Significado |\n| --- | --- | --- | --- |\n| `BRIDGE_AI_LEADSCOUT_0010` | 404 | Canal fora do workspace | O canal de provedor não pertence ao workspace |\n| `BRIDGE_AI_LEADSCOUT_0011` | 404 | Nenhum canal de provedor | O workspace não tem canais de provedor |\n| `BRIDGE_AI_LEADSCOUT_0012` | 404 | Nenhum Agente para o canal | Não há Agente de prospecção para o canal |\n| `BRIDGE_AI_LEADSCOUT_0013` | 409 | Vários Agentes para a marca | Há vários Agentes de prospecção para a marca |\n| `BRIDGE_AI_LEADSCOUT_0014` | 409 | Vários Agentes para o canal | Há vários Agentes de prospecção para o canal |\n| `BRIDGE_AI_LEADSCOUT_0015` | 500 | Falha na operação de conversa | A operação de conversa falhou |\n\n## Códigos de erro de marcas\n\nCódigos das verificações de marca na criação de uma conversa.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_BRAND_0101` | Marca obrigatória | O workspace tem marcas habilitadas; cada participante externo precisa ser associado a uma marca ou linha |\n\nRetornado como `400`. Envie `brandId` ou `providerChannelId` para cada participante externo; `extra.resources` lista os participantes que não tinham nenhum dos dois.\n\n## Códigos de erro de conversas\n\nCódigos das operações de conversas.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_CONVERSATION_0001` | Conversa não encontrada | A conversa solicitada não foi encontrada |\n| `BRIDGE_CONVERSATION_0002` | Conversa fora do workspace | A conversa não pertence ao workspace informado |\n| `BRIDGE_CONVERSATION_0003` | Já existe conversa com os mesmos participantes | Já existe uma conversa ativa com os mesmos participantes |\n| `BRIDGE_CONVERSATION_0004` | Conversa inativa | A conversa está inativa; nenhuma operação pode ser realizada nela |\n| `BRIDGE_CONVERSATION_0005` | Falha na operação de conversa | Ocorreu um erro ao executar a operação na conversa |\n| `BRIDGE_CONVERSATION_0006` | Conversa em estado inconsistente | A conversa está em um estado inconsistente; contate o suporte para resolver |\n| `BRIDGE_CONVERSATION_0007` | Conversa liberada | A conversa está liberada; `409` de `POST .../messages` |\n| `BRIDGE_CONVERSATION_0101` | Usuário interno já está na conversa | O usuário interno já participa da conversa |\n| `BRIDGE_CONVERSATION_0102` | Usuário interno não está na conversa | O usuário interno não participa da conversa |\n| `BRIDGE_CONVERSATION_0103` | Usuário externo já está na conversa | O usuário externo já participa da conversa |\n| `BRIDGE_CONVERSATION_0104` | Usuário externo não está na conversa | O usuário externo não participa da conversa |\n| `BRIDGE_CONVERSATION_0105` | Usuário externo já usa o canal | O usuário externo já usa esse canal de mensagens em alguma conversa |\n| `BRIDGE_CONVERSATION_0201` | Participantes externos obrigatórios | É necessário pelo menos um participante externo para operar em uma conversa |\n| `BRIDGE_CONVERSATION_0202` | Participantes internos obrigatórios | É necessário pelo menos um participante interno para operar em uma conversa |\n| `BRIDGE_CONVERSATION_0203` | Usuário não é administrador | O usuário não é administrador desta conversa |\n| `BRIDGE_CONVERSATION_0204` | Remoção do último administrador não permitida | A conversa precisa ter pelo menos um administrador |\n| `BRIDGE_CONVERSATION_0205` | Mínimo de usuários internos | A conversa precisa ter uma quantidade mínima de participantes internos |\n| `BRIDGE_CONVERSATION_0206` | Máximo de participantes internos excedido | A conversa excedeu o máximo de participantes internos |\n| `BRIDGE_CONVERSATION_0207` | Mínimo de participantes externos | A conversa precisa ter uma quantidade mínima de participantes externos |\n| `BRIDGE_CONVERSATION_0208` | Máximo de participantes externos excedido | A conversa excedeu o máximo de participantes externos |\n| `BRIDGE_CONVERSATION_0210` | Quantidade mínima de participantes | A conversa precisa ter uma quantidade mínima de participantes |\n| `BRIDGE_CONVERSATION_0211` | Quantidade máxima de participantes | A conversa precisa respeitar uma quantidade máxima de participantes |\n| `BRIDGE_CONVERSATION_0212` | Máximo de mensagens iniciais excedido | A quantidade máxima de mensagens iniciais foi excedida |\n| `BRIDGE_CONVERSATION_0213` | Mensagens fora da conversa | As mensagens precisam pertencer à mesma conversa |\n| `BRIDGE_CONVERSATION_0601` | Template inicial não encontrado | Um template informado na substituição da sequência inicial não existe |\n| `BRIDGE_CONVERSATION_0602` | Template inicial fora do workspace | Um template informado na substituição da sequência inicial pertence a outro workspace |\n| `BRIDGE_CONVERSATION_0603` | Template inicial não aprovado | Um template informado na substituição da sequência inicial não foi aprovado para a linha de um participante |\n| `BRIDGE_CONVERSATION_0604` | Parâmetros ausentes no template inicial | Um template da sequência inicial exige valores que só o integrador pode fornecer |\n| `BRIDGE_CONVERSATION_0605` | Parâmetros desconhecidos no template inicial | A substituição da sequência inicial informa parâmetros não declarados pelo template |\n| `BRIDGE_CONVERSATION_0606` | Parâmetros não aceitos pelo template inicial | Foram enviados parâmetros para um template inicial que não é um template de provedor WhatsApp |\n| `BRIDGE_CONVERSATION_0607` | Valores inválidos no template inicial | Valores do template inicial violam uma regra do WhatsApp e seriam rejeitados no envio |\n| `BRIDGE_CONVERSATION_0608` | Template configurado exige valores do integrador | Um template da sequência inicial do workspace precisa de valores que só o integrador pode fornecer; um administrador deve alterar a sequência |\n\nAo criar uma conversa, `BRIDGE_CONVERSATION_0105` retorna `409` com `extra.reason` igual a `PARTICIPANTS_MISMATCH`: uma conversa liberada ocupa a linha do Contato com outros Contatos ou linhas. Solicite os mesmos Contatos e linhas ou use outra linha.\n\n`BRIDGE_CONVERSATION_0601` retorna `404`, `0602` e `0603` retornam `400`, e de `0604` a `0608` retornam `422`. Veja em [parâmetros de templates iniciais](https://docs.bridge.new/pt-br/templates-and-parameters.md) o conteúdo de `extra` de cada erro e como corrigi-lo.\n\n## Códigos de erro de usuários externos\n\nCódigos das operações de usuários externos, ou Contatos.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_EXTERNAL_0001` | Usuário externo não encontrado | O usuário externo solicitado não foi encontrado |\n| `BRIDGE_EXTERNAL_0002` | Usuário externo já existe | Já existe um usuário externo com os mesmos dados de identificação |\n| `BRIDGE_EXTERNAL_0004` | Usuário externo fora do workspace | Um ou mais usuários externos não pertencem ao workspace informado |\n| `BRIDGE_EXTERNAL_0005` | Campo não configurado no usuário externo | O usuário externo não tem um campo configurado; confira as configurações do workspace ou das informações externas |\n| `BRIDGE_EXTERNAL_0007` | Celular pertence a outro Contato | O telefone já é uma identidade ativa de outro usuário externo |\n| `BRIDGE_EXTERNAL_0013` | E-mail pertence a outro Contato | O e-mail já é uma identidade ativa de outro usuário externo |\n| `BRIDGE_EXTERNAL_0101` | Falha na operação de usuário externo | Ocorreu um erro ao executar a operação no usuário externo |\n\n## Códigos de erro de usuários internos\n\nCódigos das operações de usuários internos.\n\n| Código | Título legível | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_INTERNAL_0001` | Usuário interno não encontrado | O usuário interno não foi encontrado |\n| `BRIDGE_INTERNAL_0002` | Usuários internos fora do workspace | Os usuários internos informados não pertencem ao workspace especificado |\n| `BRIDGE_INTERNAL_0003` | Usuário interno inativo | Um ou mais usuários internos estão inativos; confira o status do usuário nas configurações do workspace |\n| `BRIDGE_INTERNAL_0004` | Campo não configurado no usuário interno | O usuário interno não tem um campo configurado; confira as configurações do workspace ou das informações internas |\n| `BRIDGE_INTERNAL_0101` | Operação não aceita pelo usuário interno | O usuário interno não aceita essa operação |\n\n## Códigos de erro de canais de provedor\n\nCódigos das operações de canais de provedor.\n\n| Código | Título legível | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_PROVIDER_CHANNEL_0001` | Canal de provedor não encontrado | O canal de provedor não foi encontrado; verifique se o workspace tem canais configurados |\n\nAo criar uma conversa, esse código é retornado como `409` quando nenhuma linha de WhatsApp está livre para um Contato e não há uma conversa liberada para recuperar, ou quando o `providerChannelId` informado não está disponível para esse Contato.\n\n## Códigos de limite de requisições\n\nCódigos retornados quando um workspace excede a cota de requisições. Veja em [limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md) a cota, os cabeçalhos e um cliente que controla seu ritmo.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_RATE_LIMIT_0001` | Requisições em excesso | O workspace esgotou a cota de requisições da janela atual |\n\nEsse é o único código que deve ser repetido automaticamente, e apenas após o intervalo informado no cabeçalho `Retry-After`. Falhas de autenticação não são erros de limite, e repeti-las periodicamente não resolverá o problema.\n\n## Códigos de erro de requisição\n\nCódigos retornados antes de executar a operação, quando a própria requisição não pode ser processada. Veja no [histórico de alterações](https://docs.bridge.new/pt-br/changelog.md) os parâmetros que um endpoint deixará de aceitar.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_CORE_0101` | Formato de campo inválido | O formato do campo é inválido; forneça um valor válido |\n| `BRIDGE_CORE_0102` | Campo obrigatório ausente | A requisição não contém campos obrigatórios; revise a operação |\n| `BRIDGE_CORE_0103` | Requisição inválida | A requisição é inválida; revise o corpo e os parâmetros |\n| `BRIDGE_CORE_0104` | Cursor inválido | O cursor fornecido é inválido; use um cursor obtido em uma resposta anterior |\n\nNenhum desses erros deve ser repetido sem alterações. `detail` descreve o problema e, quando possível, identifica o campo ou parâmetro incorreto; a mesma requisição falhará da mesma forma até ser corrigida.\n\n## Códigos de erro de templates\n\nCódigos das operações de templates.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_TEMPLATE_0001` | Template de provedor não encontrado | Nenhum template de provedor encontrado para o workspace e nome informados |\n\nRetornado como `404` por `GET .../templates/{templateId}` quando o ID ou nome não corresponde a um template de WhatsApp do workspace.\n\n## Códigos de erro de workspace\n\nCódigos das operações de workspace.\n\n| Código | Título | Mensagem |\n| ---- | -------------- | ------- |\n| `BRIDGE_WORKSPACE_0001` | Workspace não encontrado | O workspace solicitado não foi encontrado |\n| `BRIDGE_WORKSPACE_0002` | Workspace fora da organização | O workspace não pertence à organização informada |\n| `BRIDGE_WORKSPACE_0003` | Workspace sem canais de provedor disponíveis | O workspace não tem canais de provedor disponíveis |\n| `BRIDGE_WORKSPACE_0004` | Campo não configurado no workspace | O workspace não tem um campo configurado; `409` de `POST .../conversations/{conversationId}/release` |\n"
    },
    {
      "title": "Histórico de alterações",
      "source": "https://docs.bridge.new/pt-br/changelog",
      "markdownUrl": "https://docs.bridge.new/pt-br/changelog.md",
      "description": "Mudanças da API Bridge que afetam sua integração, das mais recentes para as mais antigas.",
      "kind": "page",
      "contentMarkdown": "## Visão geral\n\nMudanças que afetam as chamadas que você já faz, das mais recentes para as mais antigas. Alterações aditivas, como um novo endpoint ou campo opcional, não são listadas aqui, exceto quando substituem algo que será removido; elas aparecem na referência da [API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md) quando são disponibilizadas.\n\n**Nota**\n\n  As entradas antigas abaixo não registraram datas de vigência. As datas de implantação não foram verificadas, e a ordem das entradas não define uma data de lançamento. A data de remoção dos filtros de lista obsoletos **ainda não foi anunciada**. Continue usando o contrato atual documentado até a publicação de uma mudança efetiva e use os endpoints de consulta disponíveis em novas integrações.\n\n## Melhorias na documentação\n\nEsta revisão esclarece o contrato existente da API e apresenta guias de integração por tarefa. Ela renomeia o recurso de landing pages para **Custom Connections**, explica a reutilização e a recuperação de conversas outbound e melhora as orientações de erros e webhooks. As assinaturas existentes da API e as URLs de documentação `/lead-capture` são preservadas. A data de revisão da documentação não é uma data de implantação ou descontinuação da API.\n\n---\n\n## A criação de uma conversa pode recuperar uma conversa liberada\n\n`POST /conversations` costumava retornar `409 BRIDGE_PROVIDER_CHANNEL_0001` quando nenhuma linha estava livre. Agora, se os Contatos solicitados tiverem uma conversa liberada com recuperação, ela é recuperada e retornada com `201` e seu `id` existente. Portanto, você pode receber um `id` que já armazenou. Se essa conversa tiver outros Contatos ou linhas, a requisição retorna `409 BRIDGE_CONVERSATION_0105`. Veja os detalhes na referência da [API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md).\n\n---\n\n## Encontre um contato ou usuário por um identificador\n\n**Aviso**\n\n  **Essa mudança removerá parâmetros de query que existem hoje.** Eles ainda funcionam e estão marcados como obsoletos na referência da [API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md). A data em que deixarão de ser aceitos será publicada aqui antes da mudança; os endpoints de consulta que os substituem já estão disponíveis.\n\n### O que muda\n\n**Disponível agora:** `GET /contacts/lookup` e `GET /users/lookup` retornam um contato ou usuário do Bridge — chamado de usuário interno na referência da API — por um identificador.\n\n**Obsoleto, com remoção prevista:** os endpoints de listagem deixarão de filtrar. `GET /contacts` e `GET /users` manterão apenas `limit` e `cursor`.\n\n| Parâmetro obsoleto | Substituição |\n| ------- | ----------- |\n| `GET /contacts?search=` — um telefone celular | `GET /contacts/lookup?type=PHONE&value=…` |\n| `GET /contacts?search=` — um e-mail | `GET /contacts/lookup?type=EMAIL&value=…` |\n| `GET /contacts?search=` — um nome | **Nenhuma** |\n| `GET /contacts?ownerEmail=` | **Nenhuma** |\n| `GET /users?email=` | `GET /users/lookup?type=EMAIL&value=…` |\n| `GET /users?status=` | **Nenhuma** — cada linha já contém `status` |\n\nDepois da remoção, o parâmetro será **rejeitado**, não ignorado. Enviá-lo retornará `400` com `BRIDGE_CORE_0103`, e a resposta identificará o parâmetro. Essa decisão é intencional: uma chamada que ignorasse silenciosamente o filtro retornaria a primeira página de todo o workspace, permitindo que você a interpretasse como um resultado correspondente à busca.\n\n### O que fazer\n\n**Se você pesquisa por celular ou e-mail**, migre para o endpoint de consulta correspondente. Ele retorna o mesmo objeto que a lista fornece em cada linha e retorna `404` quando não há correspondência.\n\n`type` aceita os tipos de identificador já usados pela API em outros contextos: os mesmos valores de `identifierType` de um participante de conversa. Contatos aceitam `ID`, `EMAIL` e `PHONE`; usuários do Bridge aceitam `ID` e `EMAIL`, pois o celular de um usuário interno não é um identificador consultável no Bridge.\n\n`ID` é aceito pelo mesmo motivo: um código que já trabalha com o par `{identifierType, identifier}` não deve precisar tratar um dos valores de forma diferente para montar outra URL. Ele retorna exatamente o mesmo resultado de `GET /contacts/{contactId}`, que continua sendo a URL canônica de um contato. Prefira essa URL quando já tiver o ID.\n\n```bash\n# Before\ncurl \"https://api-connect-us.bridge.new/bridge/api/v1/workspaces/$WORKSPACE/contacts?search=%2B14084029292\" \\\n  -H \"x-api-key: $BRIDGE_API_KEY\"\n\n# After\ncurl \"https://api-connect-us.bridge.new/bridge/api/v1/workspaces/$WORKSPACE/contacts/lookup?type=PHONE&value=%2B14084029292\" \\\n  -H \"x-api-key: $BRIDGE_API_KEY\"\n```\n\nUm `PHONE` é interpretado da mesma forma que o celular enviado na criação de um contato: números sem código de país usam o país padrão do workspace, e espaços e separadores são ignorados. Em um `EMAIL`, o domínio é convertido para minúsculas, mas a parte local é comparada exatamente como foi enviada.\n\n**Nota**\n\n  Um celular em formato internacional começa com `+`, que precisa ser codificado como `%2B` na query string. A maioria dos clientes HTTP faz isso quando você fornece os parâmetros em um mapa, em vez de montar a URL manualmente.\n\nUm `value` incompatível com seu `type`, como e-mail, celular ou UUID malformado, é rejeitado com `422` e `BRIDGE_CORE_0101` antes de qualquer consulta. Trate esse caso separadamente de `404` se repassar diretamente dados informados por usuários: um significa *você enviou algo que não é um identificador*; o outro, *ninguém neste workspace tem esse identificador*.\n\n**Se você filtra usuários do Bridge por status**, leia `status` em cada linha. Ele é calculado, não armazenado, e já aparece em todas as respostas. Hoje, a lista retorna apenas usuários ativos, a menos que você envie `status`; após a remoção do parâmetro, ela retornará usuários ativos e desabilitados.\n\nO mesmo vale para `GET /users/lookup`: ele retorna o usuário do Bridge ativo ou desabilitado, priorizando o ativo quando um e-mail corresponde aos dois. Hoje, `GET /users?email=` não retorna um usuário desabilitado. Portanto, confira `status` na resposta se sua aplicação deve agir apenas sobre usuários ativos.\n\n**Se você pesquisa contatos por nome**, não haverá substituição; entenda o que deixará de estar disponível. O parâmetro encontra apenas o **nome completo exato**: primeiro nome, um espaço e sobrenome. Ele nunca encontra prefixos, trechos do nome ou apenas o sobrenome. Se funciona no seu caso, você já está fornecendo o nome completo.\n\n**Se você filtra contatos por responsável**, não haverá substituição. Liste a página e filtre por `ownerId` no seu próprio código. `ownerId` é o ID do usuário do Bridge responsável pelo contato, não um e-mail. Obtenha-o uma vez com `GET /users/lookup?type=EMAIL&value=…` e compare com seu `id`.\n\n### Por quê\n\nFiltrar por esses parâmetros faz o custo da chamada depender do tamanho do workspace, não do tamanho da resposta. Buscar um contato por telefone em um workspace grande exige ler dezenas de milhares de registros para retornar um único resultado. Pedir uma página maior torna a operação mais lenta, não mais rápida. Os endpoints de consulta leem apenas os registros que contêm o identificador.\n\nPor isso, os filtros estão sendo removidos, em vez de corrigidos: quando existe uma substituição, ela é estritamente melhor. A pesquisa por nome, que não tem substituição, nunca encontrou nada além do nome completo exato.\n\n---\n\n## Tópicos relacionados\n\n- [Códigos de erro](https://docs.bridge.new/pt-br/error-codes.md) — Referência completa, incluindo `BRIDGE_CORE_0103` e `BRIDGE_CORE_0101`\n- [Referência da API REST](https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md) — Endpoints de consulta, seus parâmetros e respostas\n- [Limites de requisições](https://docs.bridge.new/pt-br/rate-limits.md) — Cota por workspace e como respeitar os intervalos de nova tentativa\n"
    },
    {
      "title": "Receba webhooks do Bridge",
      "source": "https://docs.bridge.new/pt-br/webhooks",
      "markdownUrl": "https://docs.bridge.new/pt-br/webhooks.md",
      "description": "Conecte um receptor HTTPS aos eventos do Bridge e entenda autenticação, confirmação de recebimento e processamento assíncrono.",
      "kind": "page",
      "contentMarkdown": "Webhooks enviam eventos **do Bridge para seu sistema**. Configure um callback HTTPS e assine as famílias de eventos de que sua integração precisa. O Bridge envia JSON usando `POST`; seu receptor autentica e armazena o evento antes de retornar `2xx`.\n\nUse a [API REST de integrações](https://docs.bridge.new/pt-br/credentials.md) quando seu sistema precisar ler ou alterar um recurso do Bridge. Uma assinatura de webhook, sozinha, não cria uma integração bidirecional completa com o CRM: seu receptor precisa mapear identificadores, processar o evento e implementar qualquer gravação de volta desejada por meio da operação REST documentada.\n\n## Implemente o receptor\n\n  \n\n### Escolha os eventos\n\n    Leia a [referência de eventos](https://docs.bridge.new/pt-br/webhooks/events.md) e selecione a família e a versão de assinatura adequadas ao seu fluxo.\n  \n\n  \n\n### Verifique e armazene cada requisição\n\n    Siga o guia de [verificação de assinaturas](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md) para a serialização HMAC exata e o de [recebimento de eventos](https://docs.bridge.new/pt-br/webhooks/receive-events.md) para um exemplo de caixa de entrada persistente.\n  \n\n  \n\n### Configure e teste o callback\n\n    Informe a URL, a chave de API do webhook e o segredo do cliente no [console administrativo do Bridge](https://docs.bridge.new/pt-br/webhooks/configuration.md). Verifique o callback de teste antes de ativar seu fluxo de negócio.\n  \n\n```mermaid\nsequenceDiagram\n    participant B as Bridge\n    participant R as Seu receptor\n    participant I as Caixa de entrada persistente\n    participant W as Seu processador\n    B->>R: POST do evento JSON e cabeçalhos de autenticação\n    R->>R: Verifica a chave de API, o HMAC e a política de validade\n    R->>I: Grava o evento verificado ou confirma a duplicata exata\n    I-->>R: Aceitação persistente\n    R-->>B: Confirmação 2xx\n    W->>I: Lê os eventos pendentes\n    W->>W: Aplica a ação de negócio de forma idempotente\n```\n\n\n## Mantenha as credenciais separadas\n\n| Cabeçalho | Finalidade |\n| --- | --- |\n| `X-Bridge-API-Key` | Chave de API do webhook configurada para esse callback. Compare-a com o valor esperado. |\n| `X-Bridge-Signature` | `sha256=` seguido do HMAC-SHA256 da representação canônica do evento do Bridge, usando o segredo do cliente do webhook. |\n| `X-Bridge-Timestamp` | Segundos Unix usados na verificação de validade temporal pelo receptor. O HMAC **não** inclui esse cabeçalho. |\n\nEssas credenciais de webhook são separadas da `x-api-key` da API REST e da `captureKey` de Custom Connections usada no navegador. Mantenha o segredo do cliente do webhook no servidor.\n\n## O que a confirmação de recebimento significa\n\nUma resposta `2xx` significa que seu receptor aceitou o evento. Ela não comprova que a atualização do CRM ou outra ação de negócio terminou. Persista primeiro e processe fora da requisição, para que um serviço posterior lento não atrase a confirmação.\n\nO emissor HTTP atual faz três tentativas por operação de entrega, com esperas de um e dois segundos e timeout padrão de dez segundos no socket. Isso não é uma promessa de apenas três tentativas em todo o fluxo do evento. Leia as [regras de novas tentativas, duplicatas e ordenação](https://docs.bridge.new/pt-br/webhooks/receive-events.md) antes de escolher sua política de recuperação.\n\nNão presuma entrega exatamente uma vez, ordem global de eventos ou um endpoint público de reenvio. A [referência de eventos](https://docs.bridge.new/pt-br/webhooks/events.md) descreve os payloads; o [guia do receptor](https://docs.bridge.new/pt-br/webhooks/receive-events.md) explica como tratá-los de forma confiável.\n"
    },
    {
      "title": "Verifique requisições de webhook",
      "source": "https://docs.bridge.new/pt-br/webhooks/verifying-signatures",
      "markdownUrl": "https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md",
      "description": "Verifique a chave de API do webhook e a representação HMAC exata usada pelo Bridge e elimine eventos aceitos repetidos.",
      "kind": "page",
      "contentMarkdown": "Verifique cada requisição antes de aceitá-la no seu sistema. Use a chave de API e o segredo do cliente do **webhook** configurados para esse callback; eles são separados da chave da API REST de integrações.\n\n## Cabeçalhos de autenticação\n\n| Cabeçalho | Verificação |\n| --- | --- |\n| `X-Bridge-API-Key` | Comparação em tempo constante com a chave de API do webhook configurada |\n| `X-Bridge-Signature` | `sha256=` seguido do digest hexadecimal HMAC-SHA256 em letras minúsculas |\n| `X-Bridge-Timestamp` | Segundos Unix dentro da janela temporal aceita; o exemplo permite cinco minutos para o passado ou para o futuro |\n\nOs nomes dos cabeçalhos não diferenciam maiúsculas de minúsculas.\n\n## Exatamente o que é assinado\n\nO Bridge constrói a entrada do HMAC a partir do evento JSON usando a expressão Python abaixo e depois codifica a string em UTF-8:\n\n```python\njson.dumps(event, sort_keys=True).encode(\"utf-8\")\n```\n\nEla ordena recursivamente as chaves dos objetos, preserva a ordem dos arrays, aplica escapes a caracteres não ASCII e usa os espaços padrão do Python após vírgulas e dois-pontos. Não acrescenta uma quebra de linha. A chave é o segredo do cliente codificado em UTF-8. Essa é uma convenção de serialização JSON do Python, não RFC 8785 / JCS.\n\nNão a substitua por um digest dos bytes brutos arbitrários da requisição, JSON compacto, um `JSON.stringify` genérico do JavaScript ou uma string prefixada pelo timestamp. Espaços, escapes Unicode e formatação de números podem mudar a entrada do HMAC mesmo quando o objeto interpretado parece equivalente. Use o verificador Python abaixo ou teste outra implementação com o vetor antes de conectá-la.\n\n**Aviso**\n\n  A entrada atual do HMAC contém apenas o JSON do evento. **`X-Bridge-Timestamp` não está incluído na assinatura.** Verifique a validade temporal, mas não trate o timestamp sozinho como proteção criptográfica contra reenvio: um payload e uma assinatura anteriormente válidos podem ser apresentados com outro timestamp. Autentique a chave de API do webhook e use uma caixa de entrada persistente e processamento idempotente de negócio, conforme o guia de [recebimento de eventos](https://docs.bridge.new/pt-br/webhooks/receive-events.md).\n\n## Verificador Python\n\nSalve como `bridge_webhooks.py`. Ele retorna o objeto interpretado e verificado para que o código posterior use a mesma interpretação que foi autenticada. Obtenha os segredos de variáveis de ambiente do servidor ou do seu armazenamento de segredos.\n\n```python\nimport hashlib\nimport hmac\nimport json\nimport re\nimport sqlite3\nimport time\n\n\nclass VerificationError(ValueError):\n    pass\n\n\ndef canonical_payload(event):\n    # Match Bridge's Python json.dumps defaults: sort recursively, ASCII escapes,\n    # a space after commas and colons, then UTF-8. This is not RFC 8785 / JCS.\n    return json.dumps(event, sort_keys=True).encode(\"utf-8\")\n\n\ndef _unique_object(pairs):\n    result = {}\n    for key, value in pairs:\n        if key in result:\n            raise VerificationError(\"Duplicate JSON object key\")\n        result[key] = value\n    return result\n\n\ndef verify_webhook(raw_body, headers, webhook_api_key, client_secret, *, now=None, tolerance=300):\n    headers = {key.lower(): value for key, value in headers.items()}\n    received_key = headers.get(\"x-bridge-api-key\", \"\")\n    if not received_key or not webhook_api_key or not client_secret:\n        raise VerificationError(\"Missing webhook credentials\")\n    if not hmac.compare_digest(received_key.encode(\"utf-8\"), webhook_api_key.encode(\"utf-8\")):\n        raise VerificationError(\"Invalid webhook API key\")\n\n    received_signature = headers.get(\"x-bridge-signature\", \"\")\n    if not re.fullmatch(r\"sha256=[0-9a-f]{64}\", received_signature):\n        raise VerificationError(\"Invalid signature format\")\n    timestamp = headers.get(\"x-bridge-timestamp\", \"\")\n    if not re.fullmatch(r\"[0-9]+\", timestamp):\n        raise VerificationError(\"Invalid timestamp\")\n    current_time = time.time() if now is None else now\n    if abs(current_time - int(timestamp)) > tolerance:\n        raise VerificationError(\"Timestamp outside the permitted window\")\n\n    try:\n        event = json.loads(raw_body.decode(\"utf-8\"), object_pairs_hook=_unique_object)\n    except (UnicodeDecodeError, json.JSONDecodeError) as exc:\n        raise VerificationError(\"Invalid JSON body\") from exc\n    if not isinstance(event, dict):\n        raise VerificationError(\"Expected a JSON object\")\n    expected = \"sha256=\" + hmac.new(\n        client_secret.encode(\"utf-8\"), canonical_payload(event), hashlib.sha256\n    ).hexdigest()\n    if not hmac.compare_digest(expected, received_signature):\n        raise VerificationError(\"Invalid webhook signature\")\n    return event\n\n```\n\nA janela de cinco minutos é uma política do receptor; mantenha o relógio do servidor sincronizado. O verificador também rejeita chaves JSON duplicadas e ambíguas. Não desative a autenticação ao investigar uma divergência: confira as credenciais configuradas e compare a entrada canônica com os dados de teste abaixo.\n\n## Vetor de assinatura reproduzível\n\nEstes valores são dados de teste sintéticos, não credenciais reais nem um evento para enviar ao Bridge. Ao testar a validade temporal, defina o argumento `now` do verificador como `1800000000`.\n\n| Valor | Dado de teste |\n| --- | --- |\n| Segredo do cliente | `bridge-docs-test-secret` |\n| Chave de API do webhook | `bridge-docs-test-key` |\n| Cabeçalho de timestamp | `1800000000` |\n| Assinatura esperada | `sha256=5536c29fd98baab6ffe46dd9517adb185b32202864cbb5a76146172fc0b39423` |\n\nObjeto do evento:\n\n```json\n{\n  \"eventId\": \"evt_docs_001\",\n  \"eventType\": \"contact.updated\",\n  \"entity\": \"contact\",\n  \"workspaceId\": \"ws_docs\",\n  \"timestamp\": \"2026-01-01T00:00:00Z\",\n  \"payload\": {\n    \"name\": \"José\",\n    \"tags\": [\n      \"café\",\n      \"one\"\n    ],\n    \"active\": true,\n    \"count\": 2\n  }\n}\n```\n\nString JSON exata assinada (as sequências `\\u` abaixo são barras invertidas ASCII literais, não caracteres decodificados):\n\n```text\n{\"entity\": \"contact\", \"eventId\": \"evt_docs_001\", \"eventType\": \"contact.updated\", \"payload\": {\"active\": true, \"count\": 2, \"name\": \"Jos\\u00e9\", \"tags\": [\"caf\\u00e9\", \"one\"]}, \"timestamp\": \"2026-01-01T00:00:00Z\", \"workspaceId\": \"ws_docs\"}\n```\n\nAlterar um campo deve fazer a verificação falhar. Mudar apenas a ordem das chaves de entrada ou enviar Unicode literal em vez de escapes Unicode JSON ainda deve ser validado após interpretar e reconstruir a mesma representação canônica.\n\n## Após a verificação\n\nConfirme a gravação do evento em uma caixa de entrada persistente antes de responder. Um HMAC válido confirma a representação autenticada do evento; não comprova que a ação de negócio foi executada, que o evento é novo ou que representa o estado mais recente do recurso. Continue com [entrega, duplicatas e ordenação](https://docs.bridge.new/pt-br/webhooks/receive-events.md).\n"
    },
    {
      "title": "Receba eventos de forma confiável",
      "source": "https://docs.bridge.new/pt-br/webhooks/receive-events",
      "markdownUrl": "https://docs.bridge.new/pt-br/webhooks/receive-events.md",
      "description": "Verifique, persista e confirme webhooks; depois processe com segurança duplicatas e eventos fora de ordem.",
      "kind": "page",
      "contentMarkdown": "Um receptor de webhooks tem duas responsabilidades: aceitar rapidamente um evento autenticado e processá-lo de forma confiável. Mantenha chamadas lentas ao CRM, enriquecimento e outras tarefas de negócio fora da requisição HTTP.\n\n## Receba → verifique → persista → confirme\n\n1. Leia o corpo e os cabeçalhos da requisição.\n2. Verifique a chave de API do webhook, o HMAC canônico e a política de timestamp com o [verificador](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md).\n3. Armazene atomicamente o evento verificado em uma caixa de entrada persistente ou confirme que esse evento exato já está armazenado.\n4. Retorne uma resposta `2xx` prontamente. Processe os eventos armazenados em um worker e torne cada ação de negócio idempotente.\n\nRetorne sucesso somente após a aceitação persistente. Se o armazenamento estiver indisponível, retorne uma resposta diferente de `2xx` para não confirmar a tentativa de entrega. Uma duplicata já armazenada deve receber `2xx` novamente.\n\n## Regras de novas tentativas\n\nO emissor atual faz até **três tentativas HTTP** para uma operação de entrega. Ele espera **um segundo** e depois **dois segundos** antes das tentativas restantes. Qualquer resposta `2xx` encerra essas tentativas. Uma resposta diferente de `2xx`, uma falha de conexão ou uma exceção na requisição pode acionar a próxima tentativa. O timeout padrão do socket é de **10 segundos** por tentativa; confirme em poucos segundos, em vez de contar com uma tolerância de 30 segundos.\n\nO payload, a assinatura e os cabeçalhos de timestamp são reutilizados nessa operação de entrega. Essas três tentativas limitam uma operação de envio, **não o total de todas as entregas de um evento ao longo do fluxo**. Se um evento anterior for entregue novamente, ele poderá acionar o emissor outra vez. Não há aqui promessa de um número total de tentativas ou de um prazo máximo para reenvios. Não conte com o cabeçalho de resposta `Retry-After` para definir o intervalo das tentativas do Bridge.\n\nSe todas as tentativas falharem, a entrega é considerada malsucedida. Não presuma repetição automática indefinida nem um endpoint público de reenvio. Para investigar, guarde o workspace, o tipo, o ID e o horário aproximado do evento e entre em contato com o suporte do Bridge. Não inclua credenciais de webhook em mensagens de suporte ou logs da aplicação.\n\n## Duplicatas e identidade do evento\n\nSeu serviço pode ter confirmado a gravação de um evento mesmo que o Bridge não tenha recebido sua resposta `2xx`. Uma nova tentativa não deve causar outra atualização do CRM, fatura, mensagem ou outro efeito de negócio.\n\nDelimite o registro da caixa de entrada por `workspaceId`, `eventType` e `eventId`. Armazene também um digest do evento verificado. Não presuma que `eventId` seja globalmente único em todas as famílias de notificação: algumas usam um ID derivado da entidade. Preserve payloads diferentes que compartilhem um ID e aplique idempotência de negócio à operação executada pelo worker.\n\nO exemplo abaixo elimina repetições exatas usando os três identificadores e a impressão digital SHA-256 do evento canônico. Essa é uma chave da caixa de entrada deste exemplo, não um novo campo de requisição do Bridge.\n\nNão expire um registro de deduplicação apenas porque a janela de cinco minutos do timestamp terminou. Esse cabeçalho não é assinado, portanto a janela não define um prazo seguro de expiração para proteção contra reenvios. Escolha a retenção conforme suas necessidades de conciliação de negócio e mantenha as ações no destino idempotentes. O exemplo não exclui registros da caixa de entrada automaticamente.\n\n## Receptor persistente mínimo\n\nAdicione estas definições ao módulo `bridge_webhooks.py` do guia [verifique requisições de webhook](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md). O módulo do verificador já inclui as importações usadas abaixo.\n\n```python\nclass SQLiteInbox:\n    \"\"\"Single-service example inbox. Use a shared durable store for multiple replicas.\"\"\"\n    def __init__(self, path):\n        self.path = str(path)\n        with sqlite3.connect(self.path) as db:\n            db.execute(\"\"\"CREATE TABLE IF NOT EXISTS webhook_inbox (\n                workspace_id TEXT NOT NULL, event_type TEXT NOT NULL,\n                event_id TEXT NOT NULL, fingerprint TEXT NOT NULL,\n                body TEXT NOT NULL, received_at REAL NOT NULL,\n                processed INTEGER NOT NULL DEFAULT 0,\n                PRIMARY KEY(workspace_id, event_type, event_id, fingerprint)\n            )\"\"\")\n\n    def accept(self, event):\n        identifiers = [event.get(key) for key in (\"workspaceId\", \"eventType\", \"eventId\")]\n        if not all(isinstance(value, str) and value for value in identifiers):\n            raise VerificationError(\"Missing event envelope identifiers\")\n        body = canonical_payload(event)\n        fingerprint = hashlib.sha256(body).hexdigest()\n        with sqlite3.connect(self.path, timeout=3) as db:\n            cursor = db.execute(\n                \"\"\"INSERT OR IGNORE INTO webhook_inbox\n                (workspace_id, event_type, event_id, fingerprint, body, received_at)\n                VALUES (?, ?, ?, ?, ?, ?)\"\"\",\n                (*identifiers, fingerprint, body.decode(\"utf-8\"), time.time()),\n            )\n            inserted = cursor.rowcount == 1\n        # Context manager commits before the request can be acknowledged.\n        return inserted\n\n\ndef make_wsgi_app(inbox, webhook_api_key, client_secret):\n    \"\"\"Verify, commit an inbox record, then acknowledge; workers process it later.\"\"\"\n    def app(environ, start_response):\n        if environ.get(\"REQUEST_METHOD\") != \"POST\":\n            start_response(\"405 Method Not Allowed\", [(\"Allow\", \"POST\")])\n            return [b\"\"]\n        try:\n            length = int(environ.get(\"CONTENT_LENGTH\") or \"0\")\n            if length < 1:\n                raise VerificationError(\"Missing JSON body\")\n            raw_body = environ[\"wsgi.input\"].read(length)\n            headers = {\n                \"x-bridge-api-key\": environ.get(\"HTTP_X_BRIDGE_API_KEY\", \"\"),\n                \"x-bridge-signature\": environ.get(\"HTTP_X_BRIDGE_SIGNATURE\", \"\"),\n                \"x-bridge-timestamp\": environ.get(\"HTTP_X_BRIDGE_TIMESTAMP\", \"\"),\n            }\n            event = verify_webhook(raw_body, headers, webhook_api_key, client_secret)\n            inbox.accept(event)  # A duplicate exact event is also acknowledged.\n        except (VerificationError, ValueError):\n            status, body = \"400 Bad Request\", b'{\"accepted\":false}'\n        except sqlite3.Error:\n            status, body = \"503 Service Unavailable\", b'{\"accepted\":false}'\n        else:\n            status, body = \"200 OK\", b'{\"accepted\":true}'\n        start_response(status, [(\"Content-Type\", \"application/json\"), (\"Content-Length\", str(len(body)))])\n        return [body]\n    return app\n\n```\n\nCrie a aplicação WSGI na configuração do servidor:\n\n```python\nimport os\n\nfrom bridge_webhooks import SQLiteInbox, make_wsgi_app\n\napplication = make_wsgi_app(\n    SQLiteInbox(os.environ[\"WEBHOOK_INBOX_PATH\"]),\n    os.environ[\"BRIDGE_WEBHOOK_API_KEY\"],\n    os.environ[\"BRIDGE_WEBHOOK_CLIENT_SECRET\"],\n)\n```\n\nUse um caminho persistente para o banco neste exemplo de um único serviço. Ao executar várias réplicas do receptor, use um armazenamento compartilhado com restrição atômica de unicidade equivalente. Aplique as políticas de tamanho de requisição e de rede no servidor HTTP e faça a terminação HTTPS nele.\n\nEste exemplo termina na aceitação persistente. Um worker precisa ler as linhas com `processed=0`, executar a ação de negócio de forma idempotente e marcá-las como processadas somente após o sucesso. Uma confirmação local não comprova que a ação de negócio terminou.\n\n## Ordenação e conciliação\n\nNão dependa de uma ordem global de entrega. Famílias diferentes de recursos e tentativas de entrega independentes podem se intercalar. Encaminhe cada evento pelo `eventType` publicado e use o esquema da assinatura correspondente.\n\nQuando o payload incluir `sequence`, trate-o como uma indicação de ordem do recurso ou fluxo, não como um contador global compartilhado por todos os workspaces ou famílias de eventos. Não o invente para eventos cujo esquema não tenha sequência. Preserve os timestamps e identificadores de origem e evite substituir um estado mais recente por uma notificação antiga. Quando a API REST permitir ler o recurso, consulte o estado atual se o evento deixar o resultado incerto; nos demais casos, siga a orientação da família de eventos ou contate o suporte.\n\nNão exija um campo universal `version` em todos os envelopes. Para as famílias de eventos aceitas por esse serviço, a versão configurada na assinatura seleciona o transformador registrado e o esquema de payload daquela família. Siga o esquema documentado para a família e a assinatura; não presuma uma propriedade de versão que seu envelope não publica.\n\n## Teste o receptor antes de colocar em produção\n\nVerifique o vetor de assinatura fornecido, payload alterado, chave de API incorreta, timestamps expirados e futuros, entrega duplicada após reiniciar o processo, falha de armazenamento e dois payloads diferentes com o mesmo ID. O reenvio de um payload previamente assinado com um novo timestamp demonstra por que a caixa de entrada persistente é necessária além da verificação temporal.\n\nUse o webhook de teste do console do Bridge para validar a conexão e as credenciais configuradas depois de implantar o receptor. Um teste bem-sucedido demonstra que o caminho de callback funciona; não estabelece garantias de entrega ou ordem para todos os eventos de negócio.\n"
    },
    {
      "title": "Configure webhooks",
      "source": "https://docs.bridge.new/pt-br/webhooks/configuration",
      "markdownUrl": "https://docs.bridge.new/pt-br/webhooks/configuration.md",
      "description": "Configure a URL de callback, as credenciais de webhook e as assinaturas de eventos no console administrativo do Bridge.",
      "kind": "page",
      "contentMarkdown": "Você pode gerenciar todas as configurações de webhook diretamente no [console administrativo do Bridge](https://admin.bridge.new). Isso inclui definir o endpoint, as chaves de autenticação e os tipos de evento a assinar.\n\n---\n\n## Configure os webhooks\n\nSiga estas etapas no console administrativo do Bridge:\n\n1. **Entre** no console administrativo do Bridge.\n2. Acesse **Developers → Webhooks**.\n3. Preencha os seguintes dados:\n   - **Webhook URL:** a URL HTTPS completa do seu endpoint.\n   - **API Key:** usada para identificar o workspace.\n   - **Client Secret:** usado para gerar e verificar assinaturas de webhook (HMAC-SHA256).\n4. Em **Select Event Types**, selecione os tipos de evento que deseja assinar.\n\n---\n\n## Conectores nativos de CRM e webhooks personalizados\n\nUm conector nativo de CRM e um webhook personalizado são caminhos de entrega separados. Para um CRM conectado, verifique a configuração ativa do conector e os recursos exibidos no console. Esta página não afirma que todos os eventos são sincronizados, que nenhuma configuração é necessária ou que as atualizações têm um prazo fixo em tempo real.\n\nConfigure um webhook personalizado quando seu serviço precisar receber um evento e aplicar seu próprio processamento. Você pode assinar uma família de eventos também usada por um conector nativo. Se seu receptor gravar no mesmo CRM, coordene os dois caminhos para evitar executar a mesma ação de negócio duas vezes.\n\nA confirmação de um webhook personalizado comprova apenas que seu receptor o aceitou. Use [aceitação persistente e processamento idempotente](https://docs.bridge.new/pt-br/webhooks/receive-events.md); não presuma que dois caminhos de entrega garantem atualizações do CRM exatamente uma vez.\n\n---\n\n## Opções de assinatura de eventos\n\nO Bridge oferece atualmente as seguintes categorias:\n\n### Notificações de resumo de conversa\n\nv1\n\nReceba uma notificação por dia, por conversa, quando a IA do Bridge gerar o resumo diário.\n\n- `conversation_summary.created`\n\n### Notificações de tarefas\n\nv1\n\nReceba notificações quando tarefas forem criadas ou seu estado mudar.\n\n- `task.created`\n- `task.status_changed`\n- `task.assigned`\n- `task.unassigned`\n- `task.remove_reminder`\n- `task.field_updated`\n\n### Atualizações de contatos\n\nv1\n\nReceba notificações quando contatos forem criados, atualizados ou excluídos.\n\n- `contact.created`\n- `contact.updated`\n- `contact.deleted`\n\n### Notificações de chamadas\n\nv1\n\nReceba um webhook para cada fase do ciclo de uma chamada — criada, chamando, iniciada e finalizada — além da transcrição por IA, quando estiver pronta. Chamadas não são excluídas.\n\n- `call.created`\n- `call.updated`\n- `call.transcription.created`\n\n### Notificações de reuniões\n\nv1\n\nReceba uma notificação quando uma reunião chegar ao estado CREATED. Reuniões não são excluídas, portanto somente o evento `meeting.updated` é emitido.\n\n- `meeting.updated`\n\n### Notificações de e-mail\n\nv1\n\nReceba uma notificação depois que um e-mail for processado e o resumo por IA estiver disponível. E-mails não são excluídos, portanto somente o evento `email.updated` é emitido.\n\n- `email.updated`\n\n---\n\n## Verifique sua configuração\n\nDepois que você salva a configuração, o Bridge envia automaticamente um **webhook de teste** ao endpoint para confirmar que ele está acessível e respondendo corretamente.\n\nO endpoint deve responder com:\n\n- **Código de status HTTP:** `200–299`\n- **Content-Type:** `application/json` (opcional)\n- **Tempo de resposta:** confirme prontamente após a aceitação persistente. O emissor usa timeout padrão de dez segundos no socket por tentativa HTTP; não conte com uma tolerância de 30 segundos. Veja as [regras de novas tentativas](https://docs.bridge.new/pt-br/webhooks/receive-events.md#retry-behavior).\n\n---\n\n## Gerencie os webhooks\n\nVocê pode gerenciar a configuração a qualquer momento no console:\n\n| Ação | Descrição |\n| ------------------ | ------------------------------------------------------------------- |\n| **Edit** | Atualize a URL, a chave de API ou os eventos assinados |\n| **Disable Events** | Pause temporariamente tipos de evento específicos sem excluir o webhook |\n| **Delete** | Remova permanentemente uma configuração de webhook |\n\n---\n\n## Tópicos relacionados\n\n- [Visão geral](https://docs.bridge.new/pt-br/webhooks.md)\n- [Verificação de assinaturas](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md)\n- [Tipos de evento](https://docs.bridge.new/pt-br/webhooks/events.md)\n"
    },
    {
      "title": "Eventos de webhook",
      "source": "https://docs.bridge.new/pt-br/webhooks/events",
      "markdownUrl": "https://docs.bridge.new/pt-br/webhooks/events.md",
      "description": "Famílias de eventos, exemplos de payload e versões de assinatura dos webhooks do Bridge.",
      "kind": "page",
      "contentMarkdown": "Os webhooks do Bridge entregam payloads estruturados em JSON sempre que ações específicas ocorrem no workspace. Cada evento segue um esquema consistente para facilitar a interpretação e a validação.\n\n---\n\n## Estrutura comum dos eventos\n\nO exemplo abaixo ilustra o envelope comum; `\"string\"` representa um tipo, não um valor de evento para enviar. Leia os exemplos específicos de cada família a seguir. Não presuma que `eventId` seja globalmente único entre famílias de notificação.\n\n```json\n{\n  \"eventId\": \"string\",\n  \"eventType\": \"string\",\n  \"entity\": \"string\",\n  \"workspaceId\": \"string\",\n  \"timestamp\": \"string\",\n  \"payload\": {}\n}\n```\n\n---\n\n## Notificações de resumo de conversa\n\nv1\n\nDisparadas uma vez por dia, por conversa, quando a IA do Bridge gera o resumo diário. O resumo reúne os principais pontos da troca de mensagens e os participantes internos e externos envolvidos.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | --------------------------------- | ---------------------------------------------------- |\n    | `conversation_summary.created` | Um resumo diário da conversa foi gerado |\n  \n\n  \n\n### Exemplo de payload\n\n    ```json\n    {\n      \"eventId\": \"evt_summary_001\",\n      \"eventType\": \"conversation_summary.created\",\n      \"entity\": \"conversation_summary\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-19T05:03:15.910Z\",\n      \"payload\": {\n        \"conversationId\": \"a1b2c3d4-e5f6-7890-abcd-ef1234567890\",\n        \"summaryDate\": \"2026-05-19\",\n        \"summary\": \"- Advisor asked the customer about their preferred schedule and offered to book a product demo.\\n- Customer replied they are unavailable on Monday morning.\\n- Advisor offered alternative slots later in the week and is waiting for confirmation.\",\n        \"externalUsers\": [\n          { \"id\": \"c1d2e3f4-a5b6-7890-cdef-012345678901\", \"first_name\": \"Ana\", \"last_name\": \"Garcia\", \"cellphone\": \"+57300000000\" }\n        ],\n        \"internalUsers\": [\n          { \"id\": \"d4e5f6a7-b8c9-0123-defa-234567890123\", \"first_name\": \"Bob\", \"last_name\": \"Smith\", \"cellphone\": \"+57301000000\", \"email\": \"bob.smith@example.com\" }\n        ],\n        \"initMessageId\": \"f1e2d3c4-b5a6-7890-fedc-ba0987654321\",\n        \"endMessageId\": \"a9b8c7d6-e5f4-3210-abcd-ef9876543210\",\n        \"createdAt\": \"2026-05-19T05:03:15.910Z\",\n        \"updatedAt\": \"2026-05-19T05:03:15.910Z\"\n      }\n    }\n    ```\n  \n\n---\n\n## Atualizações de tarefas\n\nv1\n\nDisparadas quando tarefas são criadas ou seu estado muda, incluindo status, atribuição e lembretes.\n\nOs payloads variam conforme o tipo de evento. O campo `details` descreve o que mudou naquele evento específico.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | ---------------------- | ------------------------------------------------- |\n    | `task.created` | Uma nova tarefa foi criada |\n    | `task.status_changed` | O status da tarefa mudou, por exemplo, de OPEN para CLOSED |\n    | `task.assigned` | Um usuário foi atribuído à tarefa |\n    | `task.unassigned` | Um usuário deixou de estar atribuído à tarefa |\n    | `task.remove_reminder` | Um lembrete da tarefa foi removido |\n    | `task.field_updated` | Um campo da tarefa foi atualizado |\n  \n\n  \n\n### Exemplos de payload\n\n    \n\n    ```json Created\n    {\n      \"eventId\": \"evt_123456789\",\n      \"eventType\": \"task.created\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:30:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"task\": {\n          \"title\": \"Sample task\",\n          \"description\": \"Example task description\",\n          \"type\": \"TASK\",\n          \"priority\": \"NORMAL\",\n          \"status\": \"OPEN\",\n          \"sourceType\": \"MANUAL\",\n          \"dueDate\": \"2026-01-20T00:00:00.000Z\",\n          \"recurrenceEnded\": false,\n          \"createdAt\": \"2026-01-15T10:30:00.000Z\",\n          \"updatedAt\": \"2026-01-15T10:30:00.000Z\"\n        },\n        \"assignees\": [\n          { \"assigneeId\": \"user_456\", \"assigneeType\": \"USER\" }\n        ],\n        \"conversations\": [\n          {\n            \"id\": \"conv_123\",\n            \"status\": \"ACTIVE\",\n            \"createdAt\": \"2026-01-14T09:10:00.000Z\",\n            \"updatedAt\": \"2026-01-14T09:10:00.000Z\"\n          }\n        ]\n      }\n    }\n    ```\n\n    ```json Assigned\n    {\n      \"eventId\": \"evt_123456790\",\n      \"eventType\": \"task.assigned\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:31:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"details\": { \"assignee\": { \"assigneeId\": \"user_456\" } }\n      }\n    }\n    ```\n\n    ```json Unassigned\n    {\n      \"eventId\": \"evt_123456791\",\n      \"eventType\": \"task.unassigned\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:32:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"details\": { \"assignee\": { \"assigneeId\": \"user_456\" } }\n      }\n    }\n    ```\n\n    ```json Status changed (open → closed)\n    {\n      \"eventId\": \"evt_123456792\",\n      \"eventType\": \"task.status_changed\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:33:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"details\": {\n          \"statusChange\": { \"fromStatus\": \"OPEN\", \"toStatus\": \"CLOSED\" }\n        }\n      }\n    }\n    ```\n\n    ```json Status changed (closed → open)\n    {\n      \"eventId\": \"evt_123456793\",\n      \"eventType\": \"task.status_changed\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:34:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"task\": {\n          \"title\": \"Sample task\",\n          \"description\": \"Example task description\",\n          \"type\": \"TASK\",\n          \"priority\": \"NORMAL\",\n          \"status\": \"OPEN\",\n          \"sourceType\": \"MANUAL\",\n          \"dueDate\": \"2026-01-20T00:00:00.000Z\",\n          \"recurrenceEnded\": false,\n          \"createdAt\": \"2026-01-15T10:30:00.000Z\",\n          \"updatedAt\": \"2026-01-15T10:34:00.000Z\"\n        },\n        \"conversations\": [\n          {\n            \"id\": \"conv_123\",\n            \"status\": \"ACTIVE\",\n            \"createdAt\": \"2026-01-14T09:10:00.000Z\",\n            \"updatedAt\": \"2026-01-14T09:10:00.000Z\"\n          }\n        ],\n        \"details\": {\n          \"statusChange\": { \"fromStatus\": \"CLOSED\", \"toStatus\": \"OPEN\" }\n        }\n      }\n    }\n    ```\n\n    ```json Reminder removed\n    {\n      \"eventId\": \"evt_123456794\",\n      \"eventType\": \"task.remove_reminder\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:35:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_456\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"details\": { \"reminder\": { \"reminderId\": \"rem_123\" } }\n      }\n    }\n    ```\n\n    ```json Field updated\n    {\n      \"eventId\": \"evt_123456795\",\n      \"eventType\": \"task.field_updated\",\n      \"entity\": \"task\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:36:00.000Z\",\n      \"payload\": {\n        \"taskId\": \"task_123\",\n        \"actorType\": \"USER\",\n        \"actorId\": \"user_123\",\n        \"task\": {\n          \"title\": \"Sample task\",\n          \"description\": \"Example updated description\",\n          \"type\": \"TASK\",\n          \"priority\": \"NORMAL\",\n          \"status\": \"OPEN\",\n          \"sourceType\": \"MANUAL\",\n          \"dueDate\": \"2026-01-20T00:00:00.000Z\",\n          \"recurrenceEnded\": false,\n          \"createdAt\": \"2026-01-15T10:30:00.000Z\",\n          \"updatedAt\": \"2026-01-15T10:36:00.000Z\"\n        },\n        \"details\": {\n          \"fieldUpdate\": { \"changedFields\": [\"description\"] }\n        }\n      }\n    }\n    ```\n\n    \n\n  \n\n---\n\n## Atualizações de contatos\n\nv1\n\nDisparadas quando registros de contatos são criados, atualizados ou excluídos.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | ----------------- | ---------------------------- |\n    | `contact.created` | Um novo contato foi criado |\n    | `contact.updated` | Um registro de contato foi atualizado |\n    | `contact.deleted` | Um registro de contato foi excluído |\n  \n\n  \n\n### Exemplos de payload\n\n    Os campos de titularidade dependem de o contato estar vinculado a um CRM externo:\n\n    - **Contatos sincronizados com CRM** contêm `crmContactId` e `crmLastSyncedAt`; a identidade do contato é gerenciada pelo CRM, não por um usuário interno do Bridge.\n    - **Contatos nativos do Bridge**, sem vínculo com CRM, contêm `internalUserOwnerId`: o usuário do Bridge responsável pelo registro.\n\n    Esses grupos são mutuamente exclusivos: um contato sincronizado não inclui `internalUserOwnerId`, e um contato não sincronizado não inclui `crmContactId` nem `crmLastSyncedAt`.\n\n    Cada entrada em `openAttributes` e `closedAttributes` inclui um `name` legível por pessoas junto de `customAttributeId`. Nos atributos fechados, `closedCustomAttributeIds` é um array de objetos `{ id, content }`, em que `content` é o rótulo de exibição da opção selecionada.\n\n    \n\n    ```json CRM-synced\n    {\n      \"eventId\": \"evt_contact_001\",\n      \"eventType\": \"contact.updated\",\n      \"entity\": \"contact\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:30:00.000Z\",\n      \"payload\": {\n        \"id\": \"contact_123\",\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\",\n        \"email\": \"john@example.com\",\n        \"cellphone\": \"+1234567890\",\n        \"languageCode\": \"EN\",\n        \"openAttributes\": [\n          {\n            \"customAttributeId\": \"attr_open_1\",\n            \"name\": \"Account Number\",\n            \"content\": \"14\"\n          }\n        ],\n        \"closedAttributes\": [\n          {\n            \"customAttributeId\": \"attr_closed_1\",\n            \"name\": \"Preferred Language\",\n            \"closedCustomAttributeIds\": [\n              { \"id\": \"opt_1\", \"content\": \"ENGLISH\" }\n            ]\n          },\n          {\n            \"customAttributeId\": \"attr_closed_2\",\n            \"name\": \"Software Tools\",\n            \"closedCustomAttributeIds\": [\n              { \"id\": \"opt_2\", \"content\": \"Go\" },\n              { \"id\": \"opt_3\", \"content\": \"Postgres\" }\n            ]\n          }\n        ],\n        \"crmContactId\": \"crm_456\",\n        \"crmLastSyncedAt\": \"2026-01-10T09:00:00.000Z\",\n        \"createdAt\": \"2026-01-01T00:00:00.000Z\",\n        \"updatedAt\": \"2026-01-15T10:30:00.000Z\"\n      }\n    }\n    ```\n\n    ```json Bridge-native (no CRM)\n    {\n      \"eventId\": \"evt_contact_002\",\n      \"eventType\": \"contact.updated\",\n      \"entity\": \"contact\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-01-15T10:32:00.000Z\",\n      \"payload\": {\n        \"id\": \"contact_456\",\n        \"firstName\": \"Jane\",\n        \"lastName\": \"Smith\",\n        \"email\": \"jane@example.com\",\n        \"cellphone\": \"+1987654321\",\n        \"languageCode\": \"EN\",\n        \"openAttributes\": [\n          {\n            \"customAttributeId\": \"attr_open_2\",\n            \"name\": \"Education level\",\n            \"content\": \"Secondary\"\n          }\n        ],\n        \"closedAttributes\": [\n          {\n            \"customAttributeId\": \"attr_closed_1\",\n            \"name\": \"Preferred Language\",\n            \"closedCustomAttributeIds\": [\n              { \"id\": \"opt_1\", \"content\": \"ENGLISH\" }\n            ]\n          },\n          {\n            \"customAttributeId\": \"attr_closed_3\",\n            \"name\": \"Gender\",\n            \"closedCustomAttributeIds\": [\n              { \"id\": \"opt_4\", \"content\": \"FEMALE\" }\n            ]\n          }\n        ],\n        \"internalUserOwnerId\": \"user_789\",\n        \"createdAt\": \"2026-01-05T15:47:49.000Z\",\n        \"updatedAt\": \"2026-01-15T10:32:00.000Z\"\n      }\n    }\n    ```\n\n    \n\n  \n\n---\n\n## Notificações de chamadas\n\nv1\n\nDisparadas à medida que uma chamada percorre seu ciclo de vida. O Bridge emite no máximo um webhook por fase do ciclo, por chamada. Assim, a integração recebe uma sequência clara de quatro fases — criação, toque, início e término — em vez de todas as transições intermediárias gravadas internamente.\n\nA fase atual pode ser determinada pelo estado da chamada e pelo status dos participantes:\n\n| Fase | Como identificar |\n| -------- | ------------------------------------------------------------------------ |\n| created | O estado é CREATED e nenhum participante ingressou ou está chamando |\n| ringing | Um participante tem status RINGING e ninguém ingressou ainda |\n| started | O estado é STARTED e dois participantes estão JOINED |\n| finished | O estado é FINISHED |\n\nChamadas não atendidas pulam a fase de início: a integração recebe apenas created, ringing e finished.\n\nQuando uma chamada termina, o Bridge processa a gravação em um fluxo assíncrono de transcrição por IA. Quando a transcrição fica pronta, a integração recebe um evento adicional `call.transcription.created` com o texto completo dividido em segmentos por interlocutor e com marcação de tempo. Esse evento chega **depois** de `call.updated (finished)`, normalmente de alguns segundos a poucos minutos depois, conforme a duração da chamada. A diarização, que identifica os interlocutores, depende da qualidade da fonte de áudio; gravações mono podem produzir um único rótulo de interlocutor para toda a transcrição.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | ----------------------------- | ----------------------------------------------------------- |\n    | `call.created` | Uma nova chamada foi provisionada |\n    | `call.updated` | Uma fase da chamada mudou: toque, início ou término |\n    | `call.transcription.created` | A transcrição por IA de uma chamada finalizada está pronta |\n  \n\n  \n\n### Exemplos de payload\n\n    \n\n    ```json Created\n    {\n      \"eventId\": \"evt_call_001\",\n      \"eventType\": \"call.created\",\n      \"entity\": \"call\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:48:05.815Z\",\n      \"payload\": {\n        \"callId\": \"call_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"messageId\": \"msg_xyz\",\n        \"callType\": \"ONE_TO_ONE\",\n        \"channelProvider\": \"WHATSAPP\",\n        \"state\": \"CREATED\",\n        \"createdAt\": \"2026-05-04T00:48:05.815Z\",\n        \"updatedAt\": \"2026-05-04T00:48:05.815Z\",\n        \"participants\": {\n          \"internal\": [\n            { \"userId\": \"user_internal_1\", \"name\": \"Jane Doe\", \"email\": \"jane@example.com\", \"status\": \"INITIALIZED\" }\n          ],\n          \"external\": [\n            { \"userId\": \"user_external_1\", \"name\": \"John Smith\", \"email\": \"john@example.com\", \"status\": \"INITIALIZED\" }\n          ]\n        }\n      }\n    }\n    ```\n\n    ```json Ringing\n    {\n      \"eventId\": \"evt_call_002\",\n      \"eventType\": \"call.updated\",\n      \"entity\": \"call\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:48:06.243Z\",\n      \"payload\": {\n        \"callId\": \"call_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"messageId\": \"msg_xyz\",\n        \"callType\": \"ONE_TO_ONE\",\n        \"channelProvider\": \"WHATSAPP\",\n        \"state\": \"CREATED\",\n        \"createdAt\": \"2026-05-04T00:48:05.815Z\",\n        \"updatedAt\": \"2026-05-04T00:48:06.243Z\",\n        \"participants\": {\n          \"internal\": [\n            { \"userId\": \"user_internal_1\", \"name\": \"Jane Doe\", \"email\": \"jane@example.com\", \"status\": \"INITIALIZED\" }\n          ],\n          \"external\": [\n            { \"userId\": \"user_external_1\", \"name\": \"John Smith\", \"email\": \"john@example.com\", \"status\": \"RINGING\" }\n          ]\n        }\n      }\n    }\n    ```\n\n    ```json Started\n    {\n      \"eventId\": \"evt_call_003\",\n      \"eventType\": \"call.updated\",\n      \"entity\": \"call\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:48:12.771Z\",\n      \"payload\": {\n        \"callId\": \"call_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"messageId\": \"msg_xyz\",\n        \"callType\": \"ONE_TO_ONE\",\n        \"channelProvider\": \"WHATSAPP\",\n        \"state\": \"STARTED\",\n        \"startedAt\": \"2026-05-04T00:48:12.125Z\",\n        \"createdAt\": \"2026-05-04T00:48:05.815Z\",\n        \"updatedAt\": \"2026-05-04T00:48:12.771Z\",\n        \"participants\": {\n          \"internal\": [\n            { \"userId\": \"user_internal_1\", \"name\": \"Jane Doe\", \"email\": \"jane@example.com\", \"status\": \"JOINED\", \"joinedAt\": \"2026-05-04T00:48:12.125Z\" }\n          ],\n          \"external\": [\n            { \"userId\": \"user_external_1\", \"name\": \"John Smith\", \"email\": \"john@example.com\", \"status\": \"JOINED\", \"joinedAt\": \"2026-05-04T00:48:12.124Z\" }\n          ]\n        }\n      }\n    }\n    ```\n\n    ```json Finished\n    {\n      \"eventId\": \"evt_call_004\",\n      \"eventType\": \"call.updated\",\n      \"entity\": \"call\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:48:20.113Z\",\n      \"payload\": {\n        \"callId\": \"call_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"messageId\": \"msg_xyz\",\n        \"callType\": \"ONE_TO_ONE\",\n        \"channelProvider\": \"WHATSAPP\",\n        \"state\": \"FINISHED\",\n        \"startedAt\": \"2026-05-04T00:48:12.125Z\",\n        \"finishedAt\": \"2026-05-04T00:48:19.389Z\",\n        \"createdAt\": \"2026-05-04T00:48:05.815Z\",\n        \"updatedAt\": \"2026-05-04T00:48:20.113Z\",\n        \"participants\": {\n          \"internal\": [\n            { \"userId\": \"user_internal_1\", \"name\": \"Jane Doe\", \"email\": \"jane@example.com\", \"status\": \"LEFT\", \"joinedAt\": \"2026-05-04T00:48:12.125Z\", \"leftAt\": \"2026-05-04T00:48:19.388Z\" }\n          ],\n          \"external\": [\n            { \"userId\": \"user_external_1\", \"name\": \"John Smith\", \"email\": \"john@example.com\", \"status\": \"LEFT\", \"joinedAt\": \"2026-05-04T00:48:12.124Z\", \"leftAt\": \"2026-05-04T00:48:19.387Z\" }\n          ]\n        }\n      }\n    }\n    ```\n\n    ```json Transcription created\n    {\n      \"eventId\": \"evt_call_005\",\n      \"eventType\": \"call.transcription.created\",\n      \"entity\": \"call\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:50:14.231Z\",\n      \"payload\": {\n        \"callId\": \"call_abc123\",\n        \"transcriptionId\": \"txn_xyz789\",\n        \"conversationId\": \"conv_xyz\",\n        \"duration\": \"27\",\n        \"startedAt\": \"2026-05-04T00:48:12.125Z\",\n        \"finishedAt\": \"2026-05-04T00:48:19.389Z\",\n        \"transcript\": [\n          { \"speaker\": \"0\", \"text\": \"Hi, how can I help you today?\", \"start\": 1.44, \"end\": 5.2 },\n          { \"speaker\": \"1\", \"text\": \"I have a question about your product.\", \"start\": 5.5, \"end\": 12.3 }\n        ]\n      }\n    }\n    ```\n\n    \n\n    Cada segmento da transcrição contém o rótulo `speaker` da diarização, normalmente `\"0\"`, `\"1\"` etc., o `text` e os deslocamentos `start`/`end` em segundos desde o início da chamada.\n  \n\n---\n\n## Notificações de reuniões\n\nv1\n\nDisparadas quando uma reunião chega ao estado CREATED. Cancelamentos de reuniões são informados pela notificação de e-mail correspondente.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | ----------------- | ------------------------------------------ |\n    | `meeting.updated` | Uma reunião chegou ao estado `CREATED` |\n  \n\n  \n\n### Exemplo de payload\n\n    ```json\n    {\n      \"eventId\": \"evt_meeting_001\",\n      \"eventType\": \"meeting.updated\",\n      \"entity\": \"meeting\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:46:40.954Z\",\n      \"payload\": {\n        \"meetingId\": \"meeting_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"messageId\": \"msg_xyz\",\n        \"subject\": \"Meeting with John Smith\",\n        \"providerType\": \"TEAMS\",\n        \"status\": \"CREATED\",\n        \"organizerInternalUserId\": \"user_internal_1\",\n        \"internalParticipants\": [\"user_internal_1\"],\n        \"externalParticipants\": [\"user_external_1\"],\n        \"startDateTime\": \"2026-05-04T01:00:00.000Z\",\n        \"endDateTime\": \"2026-05-04T01:15:00.000Z\",\n        \"createdAt\": \"2026-05-04T00:46:29.944Z\",\n        \"updatedAt\": \"2026-05-04T00:46:40.954Z\",\n        \"provider\": {\n          \"joinUrl\": \"https://teams.microsoft.com/l/meetup-join/...\",\n          \"calendarEventId\": \"AAMkADhlMWVlMWJhLWUyZTMtNDllOC...\",\n          \"chatId\": \"MWM1Zjg4MmUtZjk0Mi00YjJkLTgyNTItNmRiODNiZmM1NWEw\",\n          \"providerMeetingId\": \"MSowODJkZmFjYy1iNDZmLTRiNDItOGYzOS0xMzI0NDcyMzUwMWUq...\"\n        }\n      }\n    }\n    ```\n  \n\n---\n\n## Notificações de e-mail\n\nv1\n\nDisparadas depois que um e-mail é processado e o resumo por IA está disponível.\n\nO campo `sentFromBridge` indica a direção: true para e-mails enviados pelo workspace, false para e-mails recebidos.\n\n  \n\n### Tipos de evento\n\n    | Tipo de evento | Descrição |\n    | --------------- | ---------------------------------------------------- |\n    | `email.updated` | Um e-mail chegou ao estado resumido |\n  \n\n  \n\n### Exemplo de payload\n\n    ```json\n    {\n      \"eventId\": \"evt_email_001\",\n      \"eventType\": \"email.updated\",\n      \"entity\": \"email\",\n      \"workspaceId\": \"ws_123\",\n      \"timestamp\": \"2026-05-04T00:45:31.261Z\",\n      \"payload\": {\n        \"emailId\": \"email_abc123\",\n        \"conversationId\": \"conv_xyz\",\n        \"threadId\": \"AAQkADhlMWVlMWJhLWUyZTMtNDllOC05MDg2LWMzNjFkMTI5MjM4MA...\",\n        \"providerType\": \"OUTLOOK\",\n        \"status\": \"PROCESSED\",\n        \"subject\": \"Project update\",\n        \"sender\": \"jane@example.com\",\n        \"recipients\": [\n          { \"recipientEmail\": \"john@example.com\" }\n        ],\n        \"summary\": \"Jane confirms the project is on track and shares next steps.\",\n        \"importance\": \"NORMAL\",\n        \"sentFromBridge\": true,\n        \"hasAttachments\": false,\n        \"sentAt\": \"2026-05-04T00:45:09.000Z\",\n        \"createdAt\": \"2026-05-04T00:45:09.000Z\",\n        \"updatedAt\": \"2026-05-04T00:45:31.261Z\"\n      }\n    }\n    ```\n  \n\n---\n\n## Observações\n\n- O Bridge pode acrescentar novas categorias de eventos no futuro.\n- Sempre verifique o campo de tipo de evento para escolher qual tratador executar.\n- Configure e dê suporte à versão selecionada para cada assinatura de evento. O envelope comum não declara um campo universal `version`; não o exija nem o invente. Veja [recebimento de eventos](https://docs.bridge.new/pt-br/webhooks/receive-events.md) para tratar duplicatas e ordenação.\n\n---\n\n## Tópicos relacionados\n\n- [Visão geral](https://docs.bridge.new/pt-br/webhooks.md)\n- [Verificação de assinaturas](https://docs.bridge.new/pt-br/webhooks/verifying-signatures.md)\n- [Configuração no console](https://docs.bridge.new/pt-br/webhooks/configuration.md)\n"
    },
    {
      "title": "Custom Connections",
      "source": "https://docs.bridge.new/pt-br/lead-capture/index",
      "markdownUrl": "https://docs.bridge.new/pt-br/lead-capture/index.md",
      "description": "Use Custom Connections para registrar leads da sua landing page e colocar uma mensagem inicial de WhatsApp na fila de envio.",
      "kind": "page",
      "contentMarkdown": "## O que essa integração faz\n\nSua landing page envia um lead ao Bridge. Em seguida, o Bridge abre a conversa no WhatsApp usando um template aprovado. Você não envia a mensagem: o Bridge faz o envio.\n\n**Aviso**\n\n  **Uma resposta `202` significa que o lead foi aceito, não que a mensagem foi enviada.** A primeira mensagem de WhatsApp é transmitida depois por um serviço separado. O texto de confirmação deve dizer algo como \"entraremos em contato pelo WhatsApp em breve\", nunca \"já enviamos uma mensagem\".\n\n## O que você precisa e onde obter\n\nSão quatro valores: a URL do endpoint, sua `captureKey`, a chave do site reCAPTCHA e o nome da ação reCAPTCHA.\n\nVocê não precisa montá-los manualmente. No console administrativo do Bridge, em **LeadScout → Capture snippet**, um administrador do workspace gera um exemplo de integração que já contém os quatro valores. Ele entrega esse bloco à pessoa responsável pela página, que não precisa ter acesso ao console.\n\n**Nota**\n\n  O exemplo é um ponto de partida, não um script pronto para publicar sem adaptações. Você é responsável pelo formulário e pelo texto de consentimento. Veja os [requisitos de consentimento](https://docs.bridge.new/pt-br/lead-capture/consent.md).\n\n## Próximos passos\n\n  \n\n### [Requisitos de consentimento](https://docs.bridge.new/pt-br/lead-capture/consent.md)\n\n    O que o aceite deve informar e o que você declara ao enviá-lo.\n  \n\n  \n\n### [Requisitos de templates](https://docs.bridge.new/pt-br/lead-capture/templates.md)\n\n    Escolha um template de Utility ou Marketing compatível e entenda os requisitos de cada categoria.\n  \n\n  \n\n### [Guia de integração](https://docs.bridge.new/pt-br/lead-capture/integration.md)\n\n    Integre o formulário e trate CAPTCHA, consentimento, respostas e erros.\n  \n\n  \n\n### [Referência de erros](https://docs.bridge.new/pt-br/lead-capture/errors.md)\n\n    Todas as respostas do endpoint e quais problemas você pode corrigir.\n"
    },
    {
      "title": "Requisitos de consentimento",
      "source": "https://docs.bridge.new/pt-br/lead-capture/consent",
      "markdownUrl": "https://docs.bridge.new/pt-br/lead-capture/consent.md",
      "description": "O que o aceite deve informar e o que você declara ao enviar consent.status GRANTED.",
      "kind": "page",
      "contentMarkdown": "## O que o formulário deve conter\n\nSua landing page deve solicitar um aceite explícito antes de enviar um lead. Você define o texto, mas ele precisa cumprir dois requisitos da Meta:\n\n- **Identificar a empresa.** Não basta dizer \"nós\" ou \"nossos parceiros\": informe qual empresa entrará em contato com a pessoa.\n- **Informar que a pessoa receberá comunicações dessa empresa pelo WhatsApp.** Não basta dizer \"podemos entrar em contato\": identifique o canal.\n\nA Meta inclui formulários de sites entre as formas aceitas de obter esse consentimento. Por isso, uma caixa de seleção na landing page é suficiente, desde que o texto informe os dois pontos.\n\n**Aviso**\n\n  Uma caixa previamente marcada não representa aceite. O mesmo vale para um texto em letras pequenas sob o botão de envio, sem nenhuma interação do visitante. A pessoa precisa realizar a ação.\n\n## O que você declara\n\n**Nota**\n\n  Ao enviar `consent.status: \"GRANTED\"`, **você** declara que houve consentimento. Não verificamos, nem podemos verificar, se o visitante marcou a caixa: registramos que você nos informou esse aceite e quando ele ocorreu. Se o envio de WhatsApp da sua empresa sofrer alguma restrição, esse é o registro apresentado em seu nome.\n\nPor isso, `capturedAt` é mais importante do que pode parecer. Ele deve representar o momento em que o visitante realmente consentiu, não o momento em que seu servidor enviou a requisição nem um timestamp gerado em um processamento noturno. Se for necessário comprovar o aceite, a diferença entre esses momentos será um dos primeiros pontos analisados.\n\nEnvie o horário como um timestamp ISO 8601:\n\n```json\n{\n  \"consent\": {\n    \"status\": \"GRANTED\",\n    \"capturedAt\": \"2026-08-26T14:32:07.184Z\"\n  }\n}\n```\n\nSe não houve consentimento, não envie o lead. Um envio com qualquer status diferente de `GRANTED` é rejeitado com `BRIDGE.CAMPAIGN_LEADS.CONSENT_NOT_GRANTED`.\n\n## Um exemplo para adaptar\n\nEste exemplo é ilustrativo, não um texto padrão para copiar sem adaptações. Só você sabe o que enviará e por quê; o texto precisa refletir essa comunicação.\n\n> ☐ Concordo em receber mensagens de WhatsApp da **Acme Motors** sobre o orçamento que acabei de solicitar.\n\nO que torna o exemplo adequado: ele identifica a empresa, informa o canal e descreve o assunto das mensagens. O que o tornaria inadequado: omitir a empresa, dizer apenas \"mensagens\" sem mencionar o WhatsApp ou incluir esse aceite em uma caixa genérica de termos e condições que também trate de assuntos não relacionados.\n"
    },
    {
      "title": "Requisitos de templates",
      "source": "https://docs.bridge.new/pt-br/lead-capture/templates",
      "markdownUrl": "https://docs.bridge.new/pt-br/lead-capture/templates.md",
      "description": "Categorias de templates aceitas e orientações para abrir conversas por Custom Connections.",
      "kind": "page",
      "contentMarkdown": "## Categorias de templates aceitas\n\nO template que abre a conversa pode ser da categoria **utility** ou **marketing**:\n\n- **Templates Utility**: estritamente transacionais, relacionados ao que o visitante acabou de enviar, como a confirmação de recebimento de uma consulta. Essa categoria tem tarifas menores de conversa no WhatsApp.\n- **Templates Marketing**: podem incluir linguagem promocional, descontos, ofertas especiais ou abordagens diretas de venda. São cobrados pelas tarifas padrão de marketing do WhatsApp.\n\n**Nota**\n\n  Templates **Authentication** não podem ser usados com Custom Connections. Qualquer template configurado com a categoria `AUTHENTICATION` será rejeitado.\n\nVocê configura e submete os templates diretamente no Meta WhatsApp Manager. A aprovação é um requisito para colocar a integração em produção.\n\n## Classificação da Meta e entrega\n\n**Aviso**\n\n  A Meta classifica os templates pelo conteúdo, não apenas pela categoria selecionada na submissão. Se um template submetido como UTILITY contiver linguagem promocional, a Meta poderá reclassificá-lo como MARKETING ou rejeitá-lo.\n\nEscolher a categoria correta desde o início evita problemas de classificação e mantém a entrega e a cobrança de acordo com o esperado.\n\n## Exemplos por categoria\n\n**Utility (transacional)** — confirma o recebimento de uma consulta sem ofertas promocionais:\n\n```text\nHi {{1}}, thanks for your enquiry about the {{2}}. A member of our team will follow up here shortly.\n```\n\n**Marketing (promocional)** — inclui linguagem promocional, descontos ou ofertas de venda:\n\n```text\nHi {{1}}, thanks for your enquiry about the {{2}}. Book this week and get 15% off — reply YES to claim.\n```\n\n\n## Orientações práticas\n\n- **Escolha Utility** quando o objetivo principal for responder rapidamente de forma transacional, confirmando a solicitação do visitante. Mantenha a mensagem estritamente relacionada ao que ele enviou, sem apelos promocionais, para preservar a categoria Utility e sua tarifa menor.\n- **Escolha Marketing** quando quiser oferecer imediatamente descontos de apresentação, incentivos promocionais ou produtos do catálogo após a captura.\n- **Evite templates Authentication**: essa categoria é exclusiva para senhas de uso único e códigos de verificação e é rejeitada no envio para leads de campanha.\n- Quando a pessoa responde, inicia-se uma sessão normal de conversa. As restrições de categoria do template deixam de se aplicar às mensagens recebidas e às respostas dos atendentes ou Agentes.\n"
    },
    {
      "title": "Guia de integração",
      "source": "https://docs.bridge.new/pt-br/lead-capture/integration",
      "markdownUrl": "https://docs.bridge.new/pt-br/lead-capture/integration.md",
      "description": "Conecte um formulário de landing page ao Bridge: exemplo, CAPTCHA, consentimento, respostas e tratamento de erros.",
      "kind": "page",
      "contentMarkdown": "## O exemplo\n\nO console administrativo do Bridge fornece um exemplo de integração gerado com a configuração do workspace. A versão ampliada abaixo acrescenta validação e retorno visual do envio. Antes de executá-la, copie os valores de configuração do exemplo gerado para os campos de substituição.\n\nAdapte o formulário e o texto de consentimento à sua página. **Acme Motors é uma empresa fictícia usada no exemplo abaixo.** Substitua esse nome pela empresa que entrará em contato com o visitante e descreva as mensagens de WhatsApp que ele está aceitando receber. Veja os [requisitos de consentimento](https://docs.bridge.new/pt-br/lead-capture/consent.md). O script demonstra validação, retorno visual do envio e tratamento de erros. Mantenha inalterados os campos da requisição e a ação reCAPTCHA da configuração gerada.\n\n```html\n<!--\n  Campaign leads integration example.\n  This is a starting point, not a drop-in script: replace the form fields, labels and\n  consent copy below with your own. Keep the existing field ids, or update the matching selectors. The API fields and\n  reCAPTCHA action remain the values from your generated configuration.\n  What this does: collects a phone number (and optionally a name), mints a reCAPTCHA v3\n  token, and POSTs the lead to the campaign-leads endpoint. A 202 response means the lead\n  was accepted and queued -- a separate service sends the first WhatsApp message later, so\n  do not tell the visitor \"message sent\"; something like \"we'll message you shortly\" is\n  accurate.\n-->\n<script>\n  window.__CAMPAIGN_LEADS__ = {\"workspaceId\":\"YOUR_WORKSPACE_ID\",\"captureKey\":\"YOUR_CAPTURE_KEY\",\"endpoint\":\"https://integrations-us.app.bridge.new/api/v1/leadscout/campaign-leads\",\"brandId\":null,\"recaptchaSiteKey\":\"YOUR_RECAPTCHA_SITE_KEY\",\"recaptchaAction\":\"submit_campaign_lead\",\"trackedParams\":[]};\n</script>\n<!-- ============================================================\n     EXAMPLE FORM -- replace with your own markup and consent copy.\n     Keep the element ids (or update the selectors in the script below to match yours).\n     ============================================================ -->\n<form id=\"lead-form\" novalidate>\n  <label>\n    <span>Name (optional)</span>\n    <input id=\"lead-name\" type=\"text\" autocomplete=\"name\" />\n  </label>\n  <label>\n    <span>WhatsApp number</span>\n    <input id=\"lead-phone\" type=\"tel\" autocomplete=\"tel\" required />\n  </label>\n  <!-- The wording of this consent statement is yours to write: it is what the visitor is\n       agreeing to, and only you know what you will message them and why. -->\n  <label>\n    <input id=\"lead-consent\" type=\"checkbox\" required />\n    <span>I agree to receive WhatsApp messages from Acme Motors about the quote I just requested.</span>\n  </label>\n  <button type=\"submit\">Submit</button>\n  <p id=\"lead-result\" role=\"status\" aria-live=\"polite\"></p>\n</form>\n<script>\n  (function (config) {\n    \"use strict\";\n    var form = document.getElementById(\"lead-form\");\n    var consentBox = document.getElementById(\"lead-consent\");\n    var submitButton = form.querySelector(\"button[type=submit]\");\n    var result = document.getElementById(\"lead-result\");\n    var consentCapturedAt = null;\n    var inFlight = false;\n    var accepted = false;\n    var submissionStarted = false;\n    var responseReceived = false;\n    consentBox.addEventListener(\"change\", function () {\n      consentCapturedAt = consentBox.checked ? new Date().toISOString() : null;\n    });\n    function showResult(message) {\n      result.textContent = message;\n    }\n    function loadRecaptcha() {\n      return new Promise(function (resolve, reject) {\n        if (window.grecaptcha) {\n          resolve();\n          return;\n        }\n        var tag = document.createElement(\"script\");\n        tag.src = \"https://www.google.com/recaptcha/api.js?render=\" + config.recaptchaSiteKey;\n        tag.onload = function () {\n          resolve();\n        };\n        tag.onerror = function () {\n          reject(new Error(\"Could not load reCAPTCHA. Check the site key and the network.\"));\n        };\n        document.head.appendChild(tag);\n      });\n    }\n    // Mint the token on submit, not on page load: a reCAPTCHA v3 token is only valid for\n    // ~2 minutes, so minting it earlier means it can already be expired by the time the\n    // visitor actually submits the form.\n    function mintToken() {\n      return loadRecaptcha().then(function () {\n        return new Promise(function (resolve, reject) {\n          window.grecaptcha.ready(function () {\n            window.grecaptcha\n              .execute(config.recaptchaSiteKey, { action: config.recaptchaAction })\n              .then(resolve, reject);\n          });\n        });\n      });\n    }\n    // Allowlist, not a denylist: only utm_* params and the names you seeded in\n    // trackedParams are collected. The rest of the query string can carry ad-network\n    // click ids or session tokens that were never meant to be stored -- over-collection\n    // here is irreversible, so when in doubt leave a param out.\n    function readCampaignParams() {\n      var params = new URLSearchParams(window.location.search);\n      var collected = {};\n      params.forEach(function (value, key) {\n        if (key.indexOf(\"utm_\") === 0 || config.trackedParams.indexOf(key) !== -1) {\n          collected[key] = value;\n        }\n      });\n      return collected;\n    }\n    function buildPayload(token) {\n      return {\n        workspaceId: config.workspaceId,\n        captureKey: config.captureKey,\n        cellphone: document.getElementById(\"lead-phone\").value.trim(),\n        name: document.getElementById(\"lead-name\").value.trim() || null,\n        brandId: config.brandId,\n        // origin + pathname only, never the full URL: the query string can carry\n        // click ids or session tokens, and UTMs already travel separately in \"utm\" above.\n        landingUri: window.location.origin + window.location.pathname,\n        utm: readCampaignParams(),\n        consent: { status: \"GRANTED\", capturedAt: consentCapturedAt },\n        recaptchaToken: token,\n      };\n    }\n    form.addEventListener(\"submit\", function (event) {\n      event.preventDefault();\n      if (inFlight || accepted || !form.reportValidity()) return;\n      if (!consentBox.checked || !consentCapturedAt) {\n        // A browser can restore a previously checked control without firing change.\n        // Ask for a new explicit action instead of inventing its consent timestamp.\n        consentBox.checked = false;\n        showResult(\"Please select the WhatsApp consent checkbox before submitting.\");\n        consentBox.focus();\n        return;\n      }\n      inFlight = true;\n      submissionStarted = false;\n      responseReceived = false;\n      submitButton.disabled = true;\n      showResult(\"Submitting your request...\");\n      // A token verifies once. Every manual attempt, including a retry after a\n      // rejected request, obtains a new token. This example never retries a POST.\n      mintToken()\n        .then(function (token) {\n          var payload = buildPayload(token);\n          // The URL must identify the workspace for the browser's CORS preflight.\n          var url = config.endpoint + \"?workspaceId=\" + encodeURIComponent(config.workspaceId);\n          submissionStarted = true;\n          return fetch(url, {\n            method: \"POST\",\n            headers: { \"Content-Type\": \"application/json\" },\n            body: JSON.stringify(payload),\n          });\n        })\n        .then(function (response) {\n          responseReceived = true;\n          return response.json().catch(function () { return null; }).then(function (body) {\n            if (response.status === 202) {\n              accepted = true;\n              var reference = body && typeof body.requestId === \"string\"\n                ? \" Reference: \" + body.requestId\n                : \"\";\n              showResult(\"Request accepted. The business will process your request.\" + reference);\n              return;\n            }\n            var code = body && body.type ? body.type : \"HTTP \" + response.status;\n            if (response.status === 422 && code === \"BRIDGE.CAMPAIGN_LEADS.CAPTCHA_PROVIDER_UNAVAILABLE\") {\n              throw new Error(\"Verification is temporarily unavailable. You can try again; a new CAPTCHA token will be created.\");\n            }\n            if (response.status === 403 && code === \"BRIDGE.CAMPAIGN_LEADS.CAPTCHA_REJECTED\") {\n              throw new Error(\"The verification was rejected. You can try again with a new CAPTCHA token.\");\n            }\n            var detail = body && (body.detail || body.title);\n            throw new Error(code + (detail ? \": \" + detail : \". Check the form configuration.\"));\n          });\n        })\n        .catch(function (error) {\n          if (submissionStarted && !responseReceived) {\n            showResult(\"We could not confirm whether your request was accepted. Check with the business before submitting it again.\");\n            return;\n          }\n          showResult(error.message || \"The request could not be completed.\");\n        })\n        .finally(function () {\n          inFlight = false;\n          submitButton.disabled = accepted;\n        });\n    });\n  })(window.__CAMPAIGN_LEADS__);\n</script>\n```\n\n\n## O que o exemplo faz\n\n- Verifica os campos obrigatórios do formulário antes de obter um token de CAPTCHA.\n- Registra `consent.capturedAt` quando o visitante marca a caixa de seleção. Se o navegador restaurar um estado antigo com a caixa já marcada, solicita uma nova ação de consentimento.\n- Permite um envio por vez e mantém o botão desabilitado após a aceitação, evitando outro envio nessa instância do formulário.\n- Apresenta uma resposta `202` como aceita e enfileirada e exibe o `requestId` retornado como referência para suporte. Nunca informa que uma mensagem de WhatsApp foi entregue.\n- Mostra falhas recuperáveis de CAPTCHA e gera um token novo a cada tentativa manual. Não repete um POST automaticamente.\n- Trata uma falha de rede após o envio como um resultado incerto; não afirma que o lead foi rejeitado nem que é seguro reenviá-lo.\n\nEsse retorno visual é implementado no cliente, não representa uma garantia de deduplicação no backend. Adapte as mensagens visíveis à sua página e use a [referência de erros](https://docs.bridge.new/pt-br/lead-capture/errors.md) para o diagnóstico.\n\n## A chave de captura não é uma chave de API\n\n**Nota**\n\n  O guia de [autenticação](https://docs.bridge.new/pt-br/credentials.md) orienta a nunca colocar uma chave no frontend. Essa regra se aplica à chave da API de integrações e continua válida. A `captureKey` é um valor de outro tipo.\n\nAo contrário da `x-api-key` usada pela API de integrações, a `captureKey` foi projetada para estar no HTML da página, onde qualquer pessoa pode lê-la. Ela não concede acesso de leitura a nenhum dado: apenas identifica a qual workspace pertence um envio. O abuso é limitado por duas outras verificações: o token de reCAPTCHA e a aceitação de envios somente dos domínios cadastrados para o workspace.\n\nNunca use a chave da API de integrações aqui e nunca a coloque em uma página.\n\n## Inclua o ID do workspace na URL\n\nO ID do workspace deve estar no corpo da requisição **e** na URL, como `?workspaceId=...`. Ele precisa estar nos dois lugares porque o navegador envia uma requisição preliminar de CORS antes da requisição principal. Essa requisição preliminar não contém corpo. Sem o ID na URL, não conseguimos identificar o workspace nem retornar o cabeçalho que autoriza seu domínio, e o navegador bloqueia a requisição antes de enviá-la.\n\nÉ importante configurar isso corretamente desde o início: essa falha aparece como um erro de CORS no console do navegador, e a requisição principal não chega aos nossos logs, pois não saiu da página.\n\n## Gere o token de CAPTCHA no envio do formulário\n\nUm token reCAPTCHA v3 vale por cerca de dois minutos. Se ele for gerado no carregamento da página, muitas vezes já terá expirado quando a pessoa terminar de preencher o formulário. A rejeição retorna `403`, o que pode parecer um problema de permissão, embora a causa seja a expiração.\n\n## Gere um novo token para cada tentativa\n\nCada token pode ser verificado uma única vez. Se um envio falhar e você tentar novamente com o mesmo token, a repetição será indistinguível de um ataque e retornará o mesmo erro recebido por um bot. Sempre chame `grecaptcha.execute` novamente antes de tentar outro envio.\n\n## O que enviar\n\nA [referência do endpoint](https://docs.bridge.new/pt-br/api-reference/campaign-leads/registrar-um-lead-de-campanha.md) contém o contrato completo. Estes são os campos cujo significado não fica evidente apenas pelo esquema:\n\n### `brandId` (`string`)\n\n  A marca comercializada pela landing page, não o ID de uma linha, canal ou telefone. Obrigatório somente se o workspace tiver marcas habilitadas. **Nunca é necessário informar um ID de linha.**\n\n### `landingUri` (`string`)\n\n  A origem e o caminho da página, sem a query string. Os parâmetros UTM são enviados separadamente em `utm`, e a query string completa pode conter IDs de cliques ou tokens de sessão que não devem ser armazenados. Envie `https://example.com/offer`, não `https://example.com/offer?gclid=...`.\n\n### `consent` (`object`)\n\n  Sua declaração de que o visitante consentiu e de quando isso aconteceu. Veja os [requisitos de consentimento](https://docs.bridge.new/pt-br/lead-capture/consent.md): o texto de aceite no formulário não é opcional.\n\n### `utm` (`object`)\n\n  Coletado da query string com base em uma lista de permissões: parâmetros `utm_*` e quaisquer nomes adicionais configurados no console. Usamos uma lista de permissões, em vez de uma lista de exclusões, porque a coleta excessiva de dados não pode ser desfeita.\n\n## Após o envio\n\nUma resposta `202` significa que o lead foi aceito e colocado na fila. Isso **não** significa que uma mensagem foi enviada: o envio acontece depois, em um serviço separado. Informe ao visitante que entrará em contato em breve.\n\nQualquer outra resposta é um erro. Consulte a [referência de erros](https://docs.bridge.new/pt-br/lead-capture/errors.md) para entender cada caso e saber se você pode corrigi-lo.\n"
    },
    {
      "title": "Referência de erros",
      "source": "https://docs.bridge.new/pt-br/lead-capture/errors",
      "markdownUrl": "https://docs.bridge.new/pt-br/lead-capture/errors.md",
      "description": "Todas as respostas do endpoint de Custom Connections e quais problemas você pode corrigir.",
      "kind": "page",
      "contentMarkdown": "As respostas de erro seguem o formato de detalhes de problema da [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457): `type`, `title`, `status` e, em alguns casos, `detail`.\n\n**Nota**\n\n  **As respostas de erro não contêm um ID de requisição.** Somente uma resposta bem-sucedida `202` contém esse identificador. Se precisar de suporte, informe a URL da página e o horário aproximado.\n\n## Todas as respostas\n\n| Status | `type` | O que aconteceu | Você pode corrigir? |\n| --- | --- | --- | --- |\n| `400` | `invalid_payload` | Um campo está ausente ou tem formato inválido. | Sim |\n| `400` | `BRIDGE.CAMPAIGN_LEADS.INVALID_PHONE` | Não foi possível interpretar o telefone como um número válido. | Sim — valide antes de enviar |\n| `400` | `BRIDGE.CAMPAIGN_LEADS.CONSENT_NOT_GRANTED` | `consent.status` não era `GRANTED`. | Sim |\n| `400` | `BRIDGE.CAMPAIGN_LEADS.BRAND_OR_LINE_REQUIRED` | O workspace tem marcas habilitadas, mas nenhum `brandId` foi enviado. | Sim |\n| `403` | `BRIDGE.CAMPAIGN_LEADS.CAPTURE_DISABLED` | O recurso Custom Connections não está habilitado para esse workspace. | Não — entre em contato com o Bridge |\n| `403` | `BRIDGE.CAMPAIGN_LEADS.CAPTURE_KEY_MISMATCH` | A chave de captura está ausente ou incorreta. | Sim |\n| `403` | `BRIDGE.CAMPAIGN_LEADS.CAPTCHA_REJECTED` | O token de CAPTCHA estava ausente, expirado, já havia sido usado ou recebeu uma pontuação muito baixa. | Em alguns casos — veja abaixo |\n| `403` | `BRIDGE.CAMPAIGN_LEADS.ORIGIN_NOT_ALLOWED` | O domínio da página não está cadastrado para esse workspace. | Não — entre em contato com o Bridge |\n| `422` | `BRIDGE.CAMPAIGN_LEADS.CAPTCHA_PROVIDER_UNAVAILABLE` | Não conseguimos acessar o provedor de CAPTCHA. | É seguro tentar novamente |\n| `500` | `unexpected_error` | Ocorreu uma falha do nosso lado. | Não |\n\nSomente a primeira falha é informada. As verificações seguem esta ordem: workspace e chave de captura, telefone, consentimento, marca, CAPTCHA e, por último, domínio. Corrigir um erro pode revelar o próximo.\n\n## Sobre a rejeição do CAPTCHA\n\n`CAPTCHA_REJECTED` abrange quatro situações. Verifique como a integração trata o token antes de atribuir a rejeição à pontuação:\n\n- **O token expirou.** Ele foi gerado cedo demais. Um token reCAPTCHA v3 dura cerca de dois minutos; gere-o quando o formulário for enviado, não no carregamento da página.\n- **O token já foi usado.** Cada token pode ser verificado uma única vez. Se você repetiu um envio malsucedido sem gerar outro token, a repetição é rejeitada.\n- **Nenhum token foi enviado.** Verifique se o cliente obtém um token e o inclui em `recaptchaToken` em todos os envios.\n- **A pontuação foi muito baixa.** A verificação contra bots rejeitou essa tentativa. Não contorne essa proteção.\n\nAs quatro situações retornam o mesmo código, portanto a resposta sozinha não identifica a causa. Primeiro, confirme que o token foi incluído, gerado no momento do envio e renovado a cada tentativa.\n\n## Sobre o erro 422\n\nÉ uma falha temporária do nosso lado: não conseguimos acessar o provedor de CAPTCHA e, por isso, não foi possível decidir se o envio era legítimo.\n\n**É seguro tentar novamente.** O lead é preservado quando isso acontece, e uma nova tentativa não pode gerar uma mensagem duplicada. Gere um novo token de CAPTCHA para a tentativa, como faria em qualquer outro envio.\n\n## Sobre o erro de domínio\n\nA ordem das verificações merece atenção.\n\nO domínio da página é comparado com os domínios cadastrados para o workspace. Porém, o domínio verificado é o **informado pelo provedor de CAPTCHA**, não o que aparece nos cabeçalhos da própria requisição. Essa verificação ocorre *depois* que o token é validado.\n\nNa prática, uma página hospedada em um domínio não cadastrado falha na etapa de CAPTCHA com `ORIGIN_NOT_ALLOWED`, não com um erro de CORS. Se isso acontecer mesmo quando o restante da integração funciona, o domínio não está na configuração do workspace. Entre em contato com o Bridge para cadastrá-lo.\n"
    },
    {
      "title": "Verificar integridade",
      "source": "https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/health/verificar-integridade.md",
      "description": "Endpoint de verificação de integridade para confirmar que a API está em funcionamento.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/health`\n\n**operationId:** `health_bridge_api_health_get`\n\nEndpoint de verificação de integridade para confirmar que a API está em funcionamento.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter conversa por id",
      "source": "https://docs.bridge.new/pt-br/api-reference/conversations-api/obter-conversa-por-id",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/conversations-api/obter-conversa-por-id.md",
      "description": "Obtém uma conversa específica pelo seu identificador único no workspace.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/conversations/{conversationId}`\n\n**operationId:** `get_conversation_by_id_bridge_api_v1_workspaces__workspaceId__conversations__conversationId__get`\n\nObtém uma conversa específica pelo seu identificador único no workspace.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Atualizar conversa",
      "source": "https://docs.bridge.new/pt-br/api-reference/conversations-api/atualizar-conversa",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/conversations-api/atualizar-conversa.md",
      "description": "Atualiza os detalhes da conversa, incluindo participantes, status e nome.\n\nAceita atualizações parciais: inclua apenas os campos que deseja alterar.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `patch /bridge/api/v1/workspaces/{workspaceId}/conversations/{conversationId}`\n\n**operationId:** `update_conversation_bridge_api_v1_workspaces__workspaceId__conversations__conversationId__patch`\n\nAtualiza os detalhes da conversa, incluindo participantes, status e nome.\n\nAceita atualizações parciais: inclua apenas os campos que deseja alterar.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Consultar conversas com filtros flexíveis",
      "source": "https://docs.bridge.new/pt-br/api-reference/conversations-api/consultar-conversas-com-filtros-flex%C3%ADveis",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/conversations-api/consultar-conversas-com-filtros-flex%C3%ADveis.md",
      "description": "Consulta conversas com opções flexíveis de filtragem.\n\nPermite buscar por identificadores de usuários externos (ID, e-mail ou telefone) ou por participantes internos, com paginação e filtro por status.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/conversations`\n\n**operationId:** `get_conversations_bridge_api_v1_workspaces__workspaceId__conversations_get`\n\nConsulta conversas com opções flexíveis de filtragem.\n\nPermite buscar por identificadores de usuários externos (ID, e-mail ou telefone) ou por participantes internos, com paginação e filtro por status.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Criar conversa com identificação flexível de usuários",
      "source": "https://docs.bridge.new/pt-br/api-reference/conversations-api/criar-conversa-com-identifica%C3%A7%C3%A3o-flex%C3%ADvel-de-usu%C3%A1rios",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/conversations-api/criar-conversa-com-identifica%C3%A7%C3%A3o-flex%C3%ADvel-de-usu%C3%A1rios.md",
      "description": "Cria uma conversa com identificação flexível de usuários.\n\nOs usuários externos podem ser identificados por ID, e-mail ou telefone. Usuários internos só são atribuídos quando informados explicitamente; caso contrário, as conversas são distribuídas em rodízio por uma equipe ou ficam abertas para qualquer usuário interno disponível.\n\nQuando não há uma linha livre e os Contacts têm uma conversa liberada com exatamente os participantes solicitados, essa conversa é recuperada e retornada, mantendo seu `id` e histórico. O `name` e o `status` da solicitação não são aplicados a ela.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/conversations`\n\n**operationId:** `create_conversation_bridge_api_v1_workspaces__workspaceId__conversations_post`\n\nCria uma conversa com identificação flexível de usuários.\n\nOs usuários externos podem ser identificados por ID, e-mail ou telefone. Usuários internos só são atribuídos quando informados explicitamente; caso contrário, as conversas são distribuídas em rodízio por uma equipe ou ficam abertas para qualquer usuário interno disponível.\n\nQuando não há uma linha livre e os Contacts têm uma conversa liberada com exatamente os participantes solicitados, essa conversa é recuperada e retornada, mantendo seu `id` e histórico. O `name` e o `status` da solicitação não são aplicados a ela.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Liberar conversa",
      "source": "https://docs.bridge.new/pt-br/api-reference/conversations-api/liberar-conversa",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/conversations-api/liberar-conversa.md",
      "description": "Libera uma conversa: marca-a como liberada, remove os participantes externos e move-a para a seção RELEASED.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/conversations/{conversationId}/release`\n\n**operationId:** `release_conversation_bridge_api_v1_workspaces__workspaceId__conversations__conversationId__release_post`\n\nLibera uma conversa: marca-a como liberada, remove os participantes externos e move-a para a seção RELEASED.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Criar mensagem",
      "source": "https://docs.bridge.new/pt-br/api-reference/messages-api/criar-mensagem",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/messages-api/criar-mensagem.md",
      "description": "Cria uma mensagem em uma conversa específica.\n\nPara uma mensagem de texto ou um anexo enviado, inclua todos os campos obrigatórios: `conversationId`, `messageBody` e `enableExternalBroadcast`. Anexe os arquivos enviados usando os identificadores retornados em `mediaIds`; consulte [Enviar um anexo](/pt-br/guides/send-attachments). Uma resposta bem-sucedida retorna `messageId`; não contém uma confirmação de entrega do provedor. Consulte [Respostas e novas tentativas](/pt-br/guides/responses).",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/messages`\n\n**operationId:** `create_message_bridge_api_v1_workspaces__workspaceId__messages_post`\n\nCria uma mensagem em uma conversa específica.\n\nPara uma mensagem de texto ou um anexo enviado, inclua todos os campos obrigatórios: `conversationId`, `messageBody` e `enableExternalBroadcast`. Anexe os arquivos enviados usando os identificadores retornados em `mediaIds`; consulte [Enviar um anexo](https://docs.bridge.new/pt-br/guides/send-attachments.md). Uma resposta bem-sucedida retorna `messageId`; não contém uma confirmação de entrega do provedor. Consulte [Respostas e novas tentativas](https://docs.bridge.new/pt-br/guides/responses.md).\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter contato por um identificador",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-um-identificador.md",
      "description": "Obtém um contato específico por qualquer um de seus identificadores no workspace.\n\n`type=ID` retorna o mesmo contato que GET /contacts/{contactId}, a URL canônica de um contato e a opção preferida quando você já tem seu ID.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/contacts/lookup`\n\n**operationId:** `retrieve_contact_by_identifier_bridge_api_v1_workspaces__workspaceId__contacts_lookup_get`\n\nObtém um contato específico por qualquer um de seus identificadores no workspace.\n\n`type=ID` retorna o mesmo contato que GET /contacts/{contactId}, a URL canônica de um contato e a opção preferida quando você já tem seu ID.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter contato por id",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-id",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/obter-contato-por-id.md",
      "description": "Obtém um contato específico pelo seu identificador único no workspace.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/contacts/{contactId}`\n\n**operationId:** `retrieve_contact_by_id_bridge_api_v1_workspaces__workspaceId__contacts__contactId__get`\n\nObtém um contato específico pelo seu identificador único no workspace.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Atualizar contato",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/atualizar-contato",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/atualizar-contato.md",
      "description": "Atualiza um contato no workspace informado.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `patch /bridge/api/v1/workspaces/{workspaceId}/contacts/{contactId}`\n\n**operationId:** `update_contact_bridge_api_v1_workspaces__workspaceId__contacts__contactId__patch`\n\nAtualiza um contato no workspace informado.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Listar contatos",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/listar-contatos",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/listar-contatos.md",
      "description": "Consulta uma lista paginada de contatos do workspace.\n\nA lista é ordenada por data de criação. Os filtros `ownerEmail` e `search` estão obsoletos e serão removidos; para encontrar um contato por um identificador, use /contacts/lookup.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/contacts`\n\n**operationId:** `get_contacts_bridge_api_v1_workspaces__workspaceId__contacts_get`\n\nConsulta uma lista paginada de contatos do workspace.\n\nA lista é ordenada por data de criação. Os filtros `ownerEmail` e `search` estão obsoletos e serão removidos; para encontrar um contato por um identificador, use /contacts/lookup.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Criar contato",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-contato",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-contato.md",
      "description": "Cria um contato no workspace informado.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/contacts`\n\n**operationId:** `create_contact_bridge_api_v1_workspaces__workspaceId__contacts_post`\n\nCria um contato no workspace informado.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Criar ou atualizar contato",
      "source": "https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-ou-atualizar-contato",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/contacts-api/criar-ou-atualizar-contato.md",
      "description": "Cria ou atualiza um contato usando apenas o celular. Classifica-o como NORMAL ou PARTIAL.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/contacts/partial`\n\n**operationId:** `create_partial_contact_bridge_api_v1_workspaces__workspaceId__contacts_partial_post`\n\nCria ou atualiza um contato usando apenas o celular. Classifica-o como NORMAL ou PARTIAL.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Criar uploads pré assinados de arquivos",
      "source": "https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/files-api/criar-uploads-pr%C3%A9-assinados-de-arquivos.md",
      "description": "Carregue um anexo, como um PDF, uma imagem ou um documento, antes de criar uma mensagem. Esta operação retorna os dados de um PUT pré-assinado; os bytes do arquivo são enviados separadamente. Após o upload ser concluído, use o `mediaId` retornado na operação de envio. Siga [Enviar um anexo](/pt-br/guides/send-attachments) para as etapas de checksum, upload e mensagem.\n\nGera URLs pré-assinadas para upload de arquivos (Presigned PUT). Valida a extensão, contentType e os limites por tipo. O checksum é obrigatório: envie o resumo SHA-256 em checksumBase64 (Base64). O upload deve incluir o cabeçalho x-amz-checksum-sha256 com o mesmo valor.\n\n---\nPara fazer upload dos arquivos, você DEVE usar a URL pré-assinada retornada com o método HTTP PUT. Envie o arquivo exatamente para a URL indicada, sem modificações, conforme exigido pelo AWS S3 para PUT com URL pré-assinada. Consulte a documentação oficial do AWS S3: [Documentação do AWS S3 sobre Presigned PUT](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html).\nInclua todos os cabeçalhos obrigatórios indicados na resposta, por exemplo, 'x-amz-checksum-sha256' com o valor SHA-256 correto. A AWS rejeitará o upload se você não usar o método HTTP ou os cabeçalhos corretos.\n\n<table><tr><th>Tipo</th><th>Extensão</th><th>Tipo de conteúdo</th><th>Tamanho máximo</th></tr><tr><td rowspan=\"4\">Imagem</td><td>.jpeg</td><td>image/jpeg</td><td rowspan=\"4\">16 MB</td></tr><tr><td>.jpg</td><td>image/jpeg</td></tr><tr><td>.png</td><td>image/png</td></tr><tr><td>.webp</td><td>image/webp</td></tr><tr><td rowspan=\"2\">GIF</td><td>.gif</td><td>image/gif</td><td rowspan=\"2\">3 MB</td></tr><tr><td>.mp4</td><td>video/mp4</td></tr><tr><td rowspan=\"3\">Vídeo</td><td>.avi</td><td>video/x-msvideo</td><td rowspan=\"3\">64 MB</td></tr><tr><td>.mov</td><td>video/quicktime</td></tr><tr><td>.mp4</td><td>video/mp4</td></tr><tr><td rowspan=\"4\">Áudio</td><td>.m4a</td><td>audio/mp4</td><td rowspan=\"4\">16 MB</td></tr><tr><td>.mp3</td><td>audio/mpeg</td></tr><tr><td>.ogg</td><td>audio/ogg</td></tr><tr><td>.wav</td><td>audio/wav</td></tr><tr><td rowspan=\"8\">Documento</td><td>.doc</td><td>application/msword</td><td rowspan=\"8\">100 MB</td></tr><tr><td>.docx</td><td>application/vnd.openxmlformats-officedocument.wordprocessingml.document</td></tr><tr><td>.pdf</td><td>application/pdf</td></tr><tr><td>.ppt</td><td>application/vnd.ms-powerpoint</td></tr><tr><td>.pptx</td><td>application/vnd.openxmlformats-officedocument.presentationml.presentation</td></tr><tr><td>.txt</td><td>text/plain</td></tr><tr><td>.xls</td><td>application/vnd.ms-excel</td></tr><tr><td>.xlsx</td><td>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</td></tr></table>",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/files`\n\n**operationId:** `create_preloaded_files_bridge_api_v1_workspaces__workspaceId__files_post`\n\nCarregue um anexo, como um PDF, uma imagem ou um documento, antes de criar uma mensagem. Esta operação retorna os dados de um PUT pré-assinado; os bytes do arquivo são enviados separadamente. Após o upload ser concluído, use o `mediaId` retornado na operação de envio. Siga [Enviar um anexo](https://docs.bridge.new/pt-br/guides/send-attachments.md) para as etapas de checksum, upload e mensagem.\n\nGera URLs pré-assinadas para upload de arquivos (Presigned PUT). Valida a extensão, contentType e os limites por tipo. O checksum é obrigatório: envie o resumo SHA-256 em checksumBase64 (Base64). O upload deve incluir o cabeçalho x-amz-checksum-sha256 com o mesmo valor.\n\n---\nPara fazer upload dos arquivos, você DEVE usar a URL pré-assinada retornada com o método HTTP PUT. Envie o arquivo exatamente para a URL indicada, sem modificações, conforme exigido pelo AWS S3 para PUT com URL pré-assinada. Consulte a documentação oficial do AWS S3: [Documentação do AWS S3 sobre Presigned PUT](https://docs.aws.amazon.com/AmazonS3/latest/userguide/PresignedUrlUploadObject.html).\nInclua todos os cabeçalhos obrigatórios indicados na resposta, por exemplo, 'x-amz-checksum-sha256' com o valor SHA-256 correto. A AWS rejeitará o upload se você não usar o método HTTP ou os cabeçalhos corretos.\n\n<table><tr><th>Tipo</th><th>Extensão</th><th>Tipo de conteúdo</th><th>Tamanho máximo</th></tr><tr><td rowspan=\"4\">Imagem</td><td>.jpeg</td><td>image/jpeg</td><td rowspan=\"4\">16 MB</td></tr><tr><td>.jpg</td><td>image/jpeg</td></tr><tr><td>.png</td><td>image/png</td></tr><tr><td>.webp</td><td>image/webp</td></tr><tr><td rowspan=\"2\">GIF</td><td>.gif</td><td>image/gif</td><td rowspan=\"2\">3 MB</td></tr><tr><td>.mp4</td><td>video/mp4</td></tr><tr><td rowspan=\"3\">Vídeo</td><td>.avi</td><td>video/x-msvideo</td><td rowspan=\"3\">64 MB</td></tr><tr><td>.mov</td><td>video/quicktime</td></tr><tr><td>.mp4</td><td>video/mp4</td></tr><tr><td rowspan=\"4\">Áudio</td><td>.m4a</td><td>audio/mp4</td><td rowspan=\"4\">16 MB</td></tr><tr><td>.mp3</td><td>audio/mpeg</td></tr><tr><td>.ogg</td><td>audio/ogg</td></tr><tr><td>.wav</td><td>audio/wav</td></tr><tr><td rowspan=\"8\">Documento</td><td>.doc</td><td>application/msword</td><td rowspan=\"8\">100 MB</td></tr><tr><td>.docx</td><td>application/vnd.openxmlformats-officedocument.wordprocessingml.document</td></tr><tr><td>.pdf</td><td>application/pdf</td></tr><tr><td>.ppt</td><td>application/vnd.ms-powerpoint</td></tr><tr><td>.pptx</td><td>application/vnd.openxmlformats-officedocument.presentationml.presentation</td></tr><tr><td>.txt</td><td>text/plain</td></tr><tr><td>.xls</td><td>application/vnd.ms-excel</td></tr><tr><td>.xlsx</td><td>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</td></tr></table>\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Consultar atributos personalizados por workspaceid",
      "source": "https://docs.bridge.new/pt-br/api-reference/custom-attributes-api/consultar-atributos-personalizados-por-workspaceid",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/custom-attributes-api/consultar-atributos-personalizados-por-workspaceid.md",
      "description": "Retorna os atributos personalizados do workspace informado.\n\nPor padrão, retorna apenas atributos **ativos** (sem um `deletedAt` no passado).\n\n**Filtros:**\n- `category`: filtra por `OPEN` ou `CLOSED`. Omita para retornar todas as categorias.\n- `includeArchived`: use `true` para incluir atributos arquivados (com `deletedAt` no passado). Padrão: `false`.\n- `isRequired`: use `true` para retornar apenas atributos obrigatórios e `false` para retornar apenas opcionais. Omita para retornar todos.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/settings/attributes`\n\n**operationId:** `get_custom_attributes_by_workspace_bridge_api_v1_workspaces__workspaceId__settings_attributes_get`\n\nRetorna os atributos personalizados do workspace informado.\n\nPor padrão, retorna apenas atributos **ativos** (sem um `deletedAt` no passado).\n\n**Filtros:**\n- `category`: filtra por `OPEN` ou `CLOSED`. Omita para retornar todas as categorias.\n- `includeArchived`: use `true` para incluir atributos arquivados (com `deletedAt` no passado). Padrão: `false`.\n- `isRequired`: use `true` para retornar apenas atributos obrigatórios e `false` para retornar apenas opcionais. Omita para retornar todos.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter canais de provedores por workspace",
      "source": "https://docs.bridge.new/pt-br/api-reference/provider-channels-api/obter-canais-de-provedores-por-workspace",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/provider-channels-api/obter-canais-de-provedores-por-workspace.md",
      "description": "Obtém os canais de provedores pelo identificador do workspace.\n\nEsta resposta expõe `provider` e `identifier`, semelhante a um número de telefone, para cada canal; não retorna `providerChannelId`. Para as linhas de um Agent, leia `agents[].lines[].providerChannelId` na lista de Agents. Não substitua um ID de canal por um número de telefone. Consulte [Conceitos e identificadores](/pt-br/guides/identifiers).",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/provider-channels`\n\n**operationId:** `get_provider_channels_by_workspace_id_bridge_api_v1_workspaces__workspaceId__provider_channels_get`\n\nObtém os canais de provedores pelo identificador do workspace.\n\nEsta resposta expõe `provider` e `identifier`, semelhante a um número de telefone, para cada canal; não retorna `providerChannelId`. Para as linhas de um Agent, leia `agents[].lines[].providerChannelId` na lista de Agents. Não substitua um ID de canal por um número de telefone. Consulte [Conceitos e identificadores](https://docs.bridge.new/pt-br/guides/identifiers.md).\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter canais por workspace e tipo de provedor",
      "source": "https://docs.bridge.new/pt-br/api-reference/provider-channels-api/obter-canais-por-workspace-e-tipo-de-provedor",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/provider-channels-api/obter-canais-por-workspace-e-tipo-de-provedor.md",
      "description": "Obtém os canais de provedores pelo identificador do workspace e tipo de provedor.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/provider-channels/{messageProviderType}`\n\n**operationId:** `get_provider_channels_by_workspace_id_and_provider_type_bridge_api_v1_workspaces__workspaceId__provider_channels__messageProviderType__get`\n\nObtém os canais de provedores pelo identificador do workspace e tipo de provedor.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Iniciar conversa de saída do leadscout com um lead conhecido",
      "source": "https://docs.bridge.new/pt-br/api-reference/leadscout-api/iniciar-conversa-de-sa%C3%ADda-do-leadscout-com-um-lead-conhecido",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/leadscout-api/iniciar-conversa-de-sa%C3%ADda-do-leadscout-com-um-lead-conhecido.md",
      "description": "Inicia uma conversa de saída do LeadScout com um Contact conhecido. O Contact já deve existir. A Bridge seleciona um Agent de prospecção para uma linha de WhatsApp elegível. O template é referenciado por template.id ou template.name; id tem precedência quando ambos são informados. Ele deve existir e estar APPROVED, e qualquer Bridge User de handoffOverride deve ser válido.\n\nUm contact.providerChannelId explícito é respeitado. Sem ele, a seleção automática prefere uma linha livre, depois uma conversa liberada recuperável com este Contact e, por último, uma conversa ativa ocupada somente quando forceSend=true. A disponibilidade é avaliada por Contact em cada linha, não pela ocupação global da linha.\n\nforceSend=true reutiliza uma conversa ativa elegível; não a ignora nem cria uma nova. Uma reutilização bem-sucedida retorna alreadyInitiated=true e persiste o novo template e os acompanhamentos. Uma conversa liberada recuperável pode ser recuperada com qualquer um dos valores, mantém seu ID e retorna recovered=true. Esta opção não torna utilizáveis as conversas bloqueadas nem as liberadas não recuperáveis. A rota legada pode reutilizar uma conversa controlada por um humano ou outro Agent; ao contrário da saída de Agents, ela não exige a verificação de controle pelo Agent solicitado.\n\nUma sessão aberta do LeadScout ainda não expirada continua bloqueando uma nova solicitação de saída com 409 BRIDGE_AI_LEADSCOUT_0017; a impossibilidade de finalizar uma sessão expirada retorna 409 BRIDGE_AI_LEADSCOUT_0018. As outras validações continuam valendo. As mensagens adicionais são persistidas; a persistência não comprova a entrega nem uma espera pela resposta do lead. Uma solicitação com falha pode deixar trabalho parcial, portanto não trate forceSend como idempotência nem repita às cegas uma solicitação com resultado incerto.\n\nConsulte [o guia completo de saída](/pt-br/guides/agent-outbound) para a matriz false/true, os indicadores de resposta, as diferenças em relação à saída de Agents, os erros e a transferência.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/leadscout/outbound`\n\n**operationId:** `initiate_leadscout_outbound_bridge_api_v1_workspaces__workspaceId__leadscout_outbound_post`\n\nInicia uma conversa de saída do LeadScout com um Contact conhecido. O Contact já deve existir. A Bridge seleciona um Agent de prospecção para uma linha de WhatsApp elegível. O template é referenciado por template.id ou template.name; id tem precedência quando ambos são informados. Ele deve existir e estar APPROVED, e qualquer Bridge User de handoffOverride deve ser válido.\n\nUm contact.providerChannelId explícito é respeitado. Sem ele, a seleção automática prefere uma linha livre, depois uma conversa liberada recuperável com este Contact e, por último, uma conversa ativa ocupada somente quando forceSend=true. A disponibilidade é avaliada por Contact em cada linha, não pela ocupação global da linha.\n\nforceSend=true reutiliza uma conversa ativa elegível; não a ignora nem cria uma nova. Uma reutilização bem-sucedida retorna alreadyInitiated=true e persiste o novo template e os acompanhamentos. Uma conversa liberada recuperável pode ser recuperada com qualquer um dos valores, mantém seu ID e retorna recovered=true. Esta opção não torna utilizáveis as conversas bloqueadas nem as liberadas não recuperáveis. A rota legada pode reutilizar uma conversa controlada por um humano ou outro Agent; ao contrário da saída de Agents, ela não exige a verificação de controle pelo Agent solicitado.\n\nUma sessão aberta do LeadScout ainda não expirada continua bloqueando uma nova solicitação de saída com 409 BRIDGE_AI_LEADSCOUT_0017; a impossibilidade de finalizar uma sessão expirada retorna 409 BRIDGE_AI_LEADSCOUT_0018. As outras validações continuam valendo. As mensagens adicionais são persistidas; a persistência não comprova a entrega nem uma espera pela resposta do lead. Uma solicitação com falha pode deixar trabalho parcial, portanto não trate forceSend como idempotência nem repita às cegas uma solicitação com resultado incerto.\n\nConsulte [o guia completo de saída](https://docs.bridge.new/pt-br/guides/agent-outbound.md) para a matriz false/true, os indicadores de resposta, as diferenças em relação à saída de Agents, os erros e a transferência.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Solicitar transferência manual do leadscout para usuários internos",
      "source": "https://docs.bridge.new/pt-br/api-reference/leadscout-api/solicitar-transfer%C3%AAncia-manual-do-leadscout-para-usu%C3%A1rios-internos",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/leadscout-api/solicitar-transfer%C3%AAncia-manual-do-leadscout-para-usu%C3%A1rios-internos.md",
      "description": "Solicita a transferência manual de uma conversa controlada pelo LeadScout para um ou mais usuários internos.\n\nA solicitação é confirmada com `202 Accepted`; a atribuição é processada de forma assíncrona. A resposta repete os destinatários solicitados e um ID de rastreamento para correlação. A resolução de usuários internos (por ID ou EMAIL) ocorre depois e não é refletida nesta resposta.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/leadscout/conversations/{conversationId}/handoff`\n\n**operationId:** `request_leadscout_handoff_bridge_api_v1_workspaces__workspaceId__leadscout_conversations__conversationId__handoff_post`\n\nSolicita a transferência manual de uma conversa controlada pelo LeadScout para um ou mais usuários internos.\n\nA solicitação é confirmada com `202 Accepted`; a atribuição é processada de forma assíncrona. A resposta repete os destinatários solicitados e um ID de rastreamento para correlação. A resolução de usuários internos (por ID ou EMAIL) ocorre depois e não é refletida nesta resposta.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Descobrir as variáveis agnósticas de um modelo",
      "source": "https://docs.bridge.new/pt-br/api-reference/templates-api/descobrir-as-vari%C3%A1veis-agn%C3%B3sticas-de-um-modelo",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/templates-api/descobrir-as-vari%C3%A1veis-agn%C3%B3sticas-de-um-modelo.md",
      "description": "Retorna as variáveis de um template: `key`/`label`/`callerMustSupply`/`isCustom`/`default`, independentes da posição na Meta.\n\nNunca retorna o endereço ou índice de uma posição da Meta.\n\n`templateId` aceita o `id` ou o `name` do template. As operações de saída aceitam `template.id` ou `template.name`, com precedência para um id não vazio. A abertura de conversas usa `onboardingTemplates[].templateId`. Use o seletor exigido pela operação de envio. Consulte [a receita de templates](/pt-br/guides/send-template).\n\nUma variável com `callerMustSupply: true` não tem uma fonte declarada: quem chama deve incluir sua `key` em `parameters` ao enviar; caso contrário, o envio falha com um 422 que identifica a mesma `key`.\nUma variável com `callerMustSupply: false` é resolvida pela própria Bridge, por exemplo, o primeiro nome do destinatário, ou já tem um valor que quem chama pode substituir opcionalmente.\nUma variável com `isCustom: true` é um valor conhecido apenas por quem chama e tem um `default`: envie-a em `parameters` para usar seu próprio valor, ou omita-a ou deixe-a em branco para enviar `default`.\n\nCódigos de erro:\n- BRIDGE_CORE_0301: o workspace na rota não corresponde ao workspace de quem chama (403)\n- BRIDGE_TEMPLATE_0001: nenhuma PROVIDER_TEMPLATE foi encontrada para este workspace e identificador. Abrange igualmente um id/name desconhecido, um template de outro workspace e um template que não é PROVIDER_TEMPLATE (404); este endpoint nunca confirma a existência de um template fora do workspace de quem chama",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/templates/{templateId}`\n\n**operationId:** `get_template_discovery_bridge_api_v1_workspaces__workspaceId__templates__templateId__get`\n\nRetorna as variáveis de um template: `key`/`label`/`callerMustSupply`/`isCustom`/`default`, independentes da posição na Meta.\n\nNunca retorna o endereço ou índice de uma posição da Meta.\n\n`templateId` aceita o `id` ou o `name` do template. As operações de saída aceitam `template.id` ou `template.name`, com precedência para um id não vazio. A abertura de conversas usa `onboardingTemplates[].templateId`. Use o seletor exigido pela operação de envio. Consulte [a receita de templates](https://docs.bridge.new/pt-br/guides/send-template.md).\n\nUma variável com `callerMustSupply: true` não tem uma fonte declarada: quem chama deve incluir sua `key` em `parameters` ao enviar; caso contrário, o envio falha com um 422 que identifica a mesma `key`.\nUma variável com `callerMustSupply: false` é resolvida pela própria Bridge, por exemplo, o primeiro nome do destinatário, ou já tem um valor que quem chama pode substituir opcionalmente.\nUma variável com `isCustom: true` é um valor conhecido apenas por quem chama e tem um `default`: envie-a em `parameters` para usar seu próprio valor, ou omita-a ou deixe-a em branco para enviar `default`.\n\nCódigos de erro:\n- BRIDGE_CORE_0301: o workspace na rota não corresponde ao workspace de quem chama (403)\n- BRIDGE_TEMPLATE_0001: nenhuma PROVIDER_TEMPLATE foi encontrada para este workspace e identificador. Abrange igualmente um id/name desconhecido, um template de outro workspace e um template que não é PROVIDER_TEMPLATE (404); este endpoint nunca confirma a existência de um template fora do workspace de quem chama\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter usuário interno por um identificador",
      "source": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-um-identificador",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-um-identificador.md",
      "description": "Obtém um Bridge User específico por qualquer um de seus identificadores no workspace.\n\n`type=ID` retorna o mesmo usuário que GET /users/{userId}, a URL canônica de um usuário interno e a opção preferida quando você já tem seu ID.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/users/lookup`\n\n**operationId:** `retrieve_internal_user_by_identifier_bridge_api_v1_workspaces__workspaceId__users_lookup_get`\n\nObtém um Bridge User específico por qualquer um de seus identificadores no workspace.\n\n`type=ID` retorna o mesmo usuário que GET /users/{userId}, a URL canônica de um usuário interno e a opção preferida quando você já tem seu ID.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Obter usuário interno por id",
      "source": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-id",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/obter-usu%C3%A1rio-interno-por-id.md",
      "description": "Obtém um usuário interno específico (agente humano) pelo seu identificador único no workspace.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/users/{userId}`\n\n**operationId:** `retrieve_internal_user_by_id_bridge_api_v1_workspaces__workspaceId__users__userId__get`\n\nObtém um usuário interno específico (agente humano) pelo seu identificador único no workspace.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Listar usuários internos",
      "source": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/listar-usu%C3%A1rios-internos",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/internal-users-api/listar-usu%C3%A1rios-internos.md",
      "description": "Consulta uma lista paginada de usuários internos do workspace.\n\nA lista é ordenada por data de criação. Os filtros `email` e `status` estão obsoletos e serão removidos; para encontrar um usuário interno por um identificador, use /users/lookup.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/users`\n\n**operationId:** `get_internal_users_bridge_api_v1_workspaces__workspaceId__users_get`\n\nConsulta uma lista paginada de usuários internos do workspace.\n\nA lista é ordenada por data de criação. Os filtros `email` e `status` estão obsoletos e serão removidos; para encontrar um usuário interno por um identificador, use /users/lookup.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Listar os agents de um workspace",
      "source": "https://docs.bridge.new/pt-br/api-reference/agents-api/listar-os-agents-de-um-workspace",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/agents-api/listar-os-agents-de-um-workspace.md",
      "description": "Lista os Agents do workspace com seu status, disponibilidade e linhas.\n\nInclui todos os Agents, independentemente do status; `available` indica se podem iniciar conversas. Uma página pode conter menos itens que `limit`; continue a paginação enquanto `cursor` não for null.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `get /bridge/api/v1/workspaces/{workspaceId}/agents`\n\n**operationId:** `list_agents_bridge_api_v1_workspaces__workspaceId__agents_get`\n\nLista os Agents do workspace com seu status, disponibilidade e linhas.\n\nInclui todos os Agents, independentemente do status; `available` indica se podem iniciar conversas. Uma página pode conter menos itens que `limit`; continue a paginação enquanto `cursor` não for null.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Iniciar conversa de saída com um contact como agent específico",
      "source": "https://docs.bridge.new/pt-br/api-reference/agents-api/iniciar-conversa-de-sa%C3%ADda-com-um-contact-como-agent-espec%C3%ADfico",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/agents-api/iniciar-conversa-de-sa%C3%ADda-com-um-contact-como-agent-espec%C3%ADfico.md",
      "description": "Inicia uma conversa de saída com um Contact conhecido, atendida pelo Agent indicado.\n\nFunciona com Agents LeadScout e Service. Primeiro é resolvido o Contact e depois o Agent, que deve existir no workspace e estar disponível (consulte `GET /agents`). O template é referenciado por `template.id` ou `template.name` (id tem precedência quando ambos são enviados), deve existir e estar APPROVED, e qualquer Bridge User de `handoffOverride` deve ser válido. Se `template.media.mediaId` for desconhecido, a solicitação falha com 400 `BRIDGE_AI_LEADSCOUT_0016` somente depois de a conversa ser criada ou recuperada, portanto uma nova tentativa após esse erro pode responder de forma diferente. As regras do corpo (`consent.status=GRANTED` sem `capturedAt`, ou `template.media` sem exatamente um de `mediaId` ou `url`) falham com 400 `BRIDGE_CORE_0103`.\n\nA conversa é aberta em uma das linhas ativas de WhatsApp do Agent, sob seu controle, com o template como primeira mensagem. A linha é escolhida nesta ordem:\n- Uma linha livre.\n- Caso contrário, uma linha com uma conversa liberada recuperável com este Contact. A recuperação retorna `recovered=true` e substitui o contexto de saída anterior e `agentContext`. Isso acontece mesmo com `forceSend=false`.\n- Se nenhuma linha estiver livre ou for recuperável: `forceSend=false` (padrão) falha com 409 `BRIDGE_AI_LEADSCOUT_0008`; `forceSend=true` reutiliza uma linha ocupada por uma conversa ativa com este Contact, dando preferência a uma controlada por este Agent. Se a conversa escolhida for controlada por outro Agent ou por um Bridge User, a chamada falha com 409 `BRIDGE_AI_AGENT_OUTBOUND_0006` e nada é gravado. Libere-a primeiro e tente novamente. Linhas cuja conversa está bloqueada ou foi liberada sem recuperação nunca são usadas; assim, se nenhuma linha estiver ocupada por uma conversa ativa, a chamada falha com 409 `BRIDGE_AI_LEADSCOUT_0008` mesmo com `forceSend=true`.\n\n`contact.providerChannelId` é uma preferência: a linha indicada é usada quando está livre ou é recuperável; caso contrário, a mesma ordem é aplicada entre todas as linhas do Agent. Entre as linhas ocupadas, uma controlada por este Agent tem prioridade; se nenhuma for, a linha indicada é reutilizada (e pode falhar com 0006).\n\nA reutilização de uma conversa depende do tipo de Agent:\n- LeadScout: se sua sessão do LeadScout ainda estiver aberta e não expirada, a chamada falha com 409 `BRIDGE_AI_LEADSCOUT_0017` (`extra` inclui `conversationId`, `sessionId` e `stage`). Se uma sessão expirada não puder ser finalizada, falha com 409 `BRIDGE_AI_LEADSCOUT_0018`.\n- Service Agent: uma sessão de serviço aberta e não expirada continua; uma sessão expirada é encerrada como abandonada e uma nova é aberta.\n\nConsulte [o guia completo de saída](/pt-br/guides/agent-outbound) para os pré-requisitos, a tabela de decisão de forceSend, a recuperação, o trabalho parcial e as decisões seguras de nova tentativa.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /bridge/api/v1/workspaces/{workspaceId}/agents/{agentId}/outbound`\n\n**operationId:** `start_agent_outbound_bridge_api_v1_workspaces__workspaceId__agents__agentId__outbound_post`\n\nInicia uma conversa de saída com um Contact conhecido, atendida pelo Agent indicado.\n\nFunciona com Agents LeadScout e Service. Primeiro é resolvido o Contact e depois o Agent, que deve existir no workspace e estar disponível (consulte `GET /agents`). O template é referenciado por `template.id` ou `template.name` (id tem precedência quando ambos são enviados), deve existir e estar APPROVED, e qualquer Bridge User de `handoffOverride` deve ser válido. Se `template.media.mediaId` for desconhecido, a solicitação falha com 400 `BRIDGE_AI_LEADSCOUT_0016` somente depois de a conversa ser criada ou recuperada, portanto uma nova tentativa após esse erro pode responder de forma diferente. As regras do corpo (`consent.status=GRANTED` sem `capturedAt`, ou `template.media` sem exatamente um de `mediaId` ou `url`) falham com 400 `BRIDGE_CORE_0103`.\n\nA conversa é aberta em uma das linhas ativas de WhatsApp do Agent, sob seu controle, com o template como primeira mensagem. A linha é escolhida nesta ordem:\n- Uma linha livre.\n- Caso contrário, uma linha com uma conversa liberada recuperável com este Contact. A recuperação retorna `recovered=true` e substitui o contexto de saída anterior e `agentContext`. Isso acontece mesmo com `forceSend=false`.\n- Se nenhuma linha estiver livre ou for recuperável: `forceSend=false` (padrão) falha com 409 `BRIDGE_AI_LEADSCOUT_0008`; `forceSend=true` reutiliza uma linha ocupada por uma conversa ativa com este Contact, dando preferência a uma controlada por este Agent. Se a conversa escolhida for controlada por outro Agent ou por um Bridge User, a chamada falha com 409 `BRIDGE_AI_AGENT_OUTBOUND_0006` e nada é gravado. Libere-a primeiro e tente novamente. Linhas cuja conversa está bloqueada ou foi liberada sem recuperação nunca são usadas; assim, se nenhuma linha estiver ocupada por uma conversa ativa, a chamada falha com 409 `BRIDGE_AI_LEADSCOUT_0008` mesmo com `forceSend=true`.\n\n`contact.providerChannelId` é uma preferência: a linha indicada é usada quando está livre ou é recuperável; caso contrário, a mesma ordem é aplicada entre todas as linhas do Agent. Entre as linhas ocupadas, uma controlada por este Agent tem prioridade; se nenhuma for, a linha indicada é reutilizada (e pode falhar com 0006).\n\nA reutilização de uma conversa depende do tipo de Agent:\n- LeadScout: se sua sessão do LeadScout ainda estiver aberta e não expirada, a chamada falha com 409 `BRIDGE_AI_LEADSCOUT_0017` (`extra` inclui `conversationId`, `sessionId` e `stage`). Se uma sessão expirada não puder ser finalizada, falha com 409 `BRIDGE_AI_LEADSCOUT_0018`.\n- Service Agent: uma sessão de serviço aberta e não expirada continua; uma sessão expirada é encerrada como abandonada e uma nova é aberta.\n\nConsulte [o guia completo de saída](https://docs.bridge.new/pt-br/guides/agent-outbound.md) para os pré-requisitos, a tabela de decisão de forceSend, a recuperação, o trabalho parcial e as decisões seguras de nova tentativa.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    },
    {
      "title": "Registrar um lead de campanha",
      "source": "https://docs.bridge.new/pt-br/api-reference/campaign-leads/registrar-um-lead-de-campanha",
      "markdownUrl": "https://docs.bridge.new/pt-br/api-reference/campaign-leads/registrar-um-lead-de-campanha.md",
      "description": "Registra um lead captado pela página de destino de um tenant e coloca na fila a primeira mensagem de saída do WhatsApp. Um 202 significa que o lead foi aceito, não que uma mensagem foi enviada.",
      "kind": "operation",
      "contentMarkdown": "**Referência da operação:** `post /leadscout/campaign-leads`\n\n**operationId:** `create_campaign_lead_leadscout_campaign_leads_post`\n\nRegistra um lead captado pela página de destino de um tenant e coloca na fila a primeira mensagem de saída do WhatsApp. Um 202 significa que o lead foi aceito, não que uma mensagem foi enviada.\n\n[Contrato OpenAPI exato](https://docs.bridge.new/pt-br/api-reference/campaign-leads.openapi.yaml)\n\nEste corpus contém guias e descrições de operações. Ele não inclui todos os schemas de requisição e resposta. Leia o contrato OpenAPI vinculado antes de gerar uma requisição.\n"
    }
  ]
}
