Atendimento pela API

Monte seu próprio inbox com conversas, atribuições, respostas compartilhadas e ferramentas do Inbox, mantendo as permissões da Conta e o controle de alterações simultâneas.

Use a base https://botozap.com.br/api/v1 com Authorization: Bearer $BOTOZAP_KEY ou X-API-Key. A Conta é derivada da chave. Não envie account_id no corpo. Os exemplos abaixo mostram o JSON enviado depois desse prefixo.

Para configurar o agente que atende pelo WhatsApp, gerar uma sugestão de resposta ou pausar a automação de uma conversa, consulte Agente de IA pela API. Essas operações exigem agents:read ou agents:write, conforme a rota.

Permissões e compatibilidade

EscopoPermite
saved_replies:readListar e consultar respostas compartilhadas.
saved_replies:writeCriar, editar e excluir respostas compartilhadas.
inbox:readConsultar notas, retornos e estado operacional da conversa.
inbox:writeAlterar notas, retornos, arquivamento e adiamento.

Leitura e escrita são permissões independentes. Chaves existentes conservam seus escopos; estas rotas não alteram os contratos de mensagens, contatos ou conversas já utilizados pela sua integração. Para ler antes de editar, conceda os dois escopos do recurso. Respostas pessoais e rascunhos ficam restritos à sessão da pessoa no painel e não são expostos à API.

Respostas compartilhadas não aceitam chaves sandbox: retornam 403 sandbox_forbidden. Conversas, atribuições e ferramentas do Inbox aceitam sandbox, mas só acessam conversas de Contas de canal do mesmo ambiente da chave. Uma conversa live consultada com chave sandbox (ou uma do sandbox com chave live) retorna 404.

Montar um inbox externo

Estas rotas dão o necessário para listar conversas, abrir a thread, distribuir o atendimento e operar notas e retornos no seu sistema. A thread de mensagens e o envio ficam em Enviar mensagens.

EscopoRotas
conversations:readListar e consultar conversas e atribuições.
conversations:writeEncerrar conversas e criar ou alterar atribuições.
team:readListar as pessoas da Conta em GET /users.
agents:writePausar e retomar o agente de IA na conversa.

Listar conversas

GET /conversations?status=active&include=last_message&limit=50

A lista usa paginação por cursor (limit até 100, after e before), da conversa criada mais recentemente para a mais antiga, e aceita chave sandbox, restrita ao ambiente da chave. Filtros:

ParâmetroEfeito
customer_idConversas das Contas de canal do Cliente. Cliente de outra Conta retorna 422 invalid_customer.
phone_number_idID Meta ou UUID interno do Número.
channel, channel_account_idCanal (whatsapp ou instagram) ou Conta de canal específica.
statusactive (não encerrada e com a janela de 24 horas aberta) ou ended (encerrada pelo painel ou pela API, ou com a janela fechada).
contactBusca parcial no nome, @username, telefone ou wa_id do contato. phone_number é um alias desse filtro, não do Número.
include=last_messageAcrescenta last_message a cada conversa, ou null sem mensagens. Outro valor retorna 422 invalid_include.

Cada conversa traz id, channel, channel_account, phone_number_id, phone_number_meta_id, display_phone_number, contact_id, contact (name, phone, username, wa_id), status, closed_at (quando foi encerrada; null se aberta), window_expires_at, last_message_at, last_read_at e created_at. last_message usa os mesmos nomes de /messages: id, wamid, direction, type, status, content, event_at, wa_timestamp e created_at. last_read_at reflete a leitura no painel e é somente leitura na API.

Consultar e encerrar uma conversa

GET /conversations/{id} retorna a mesma forma. PATCH /conversations/{id} recebe {"status":"ended"} ou {"status":"active"}. ended encerra a conversa exatamente como o botão Encerrar da tela de Conversas: ela sai da lista padrão do painel, ganha closed_at e volta sozinha quando o contato escrever de novo. active a reabre, como o botão Reabrir. Nenhum dos dois altera a janela de 24 horas da Meta, que só reabre com uma nova mensagem do contato: por isso active numa conversa com a janela fechada continua respondendo status: "ended". Se o contato mandar uma mensagem no mesmo instante do encerramento, a conversa continua aberta e a resposta é 409 conversation_changed. Outro valor retorna 422 invalid_status. As duas rotas aceitam chave sandbox, restrita ao ambiente da chave.

Atribuições

MétodoCaminhoContrato
GET/conversations/{id}/assignmentsHistórico paginado por page e per_page; ?active=true ou false filtra.
POST/conversations/{id}/assignmentsCorpo user_id e notes opcional. 201 com a nova atribuição ativa.
GET/conversations/{id}/assignments/{assignmentId}Uma atribuição.
PATCH/conversations/{id}/assignments/{assignmentId}Campos opcionais user_id, notes (texto ou null) e active.
POST /conversations/{id}/assignments
{ "user_id": "UUID-DO-MEMBRO", "notes": "Cliente pediu retorno à tarde" }

PATCH /conversations/{id}/assignments/{assignmentId}
{ "active": false }

Cada conversa tem no máximo uma atribuição ativa. Atribuir de novo desativa a anterior na mesma operação, e o histórico é preservado. active: false desatribui; active: true reativa e desativa a atual. notes aceita até 4096 caracteres. Cada item traz id, conversation_id, user_id, notes, active, created_at e updated_at.

Pessoa fora da Conta retorna 422 invalid_user; notes que não é texto, 422 invalid_notes; active que não é booleano, 422 invalid_active. Alterações simultâneas na mesma conversa retornam 409 assignment_conflict: releia e tente de novo. Conversa ou atribuição de outra Conta ou de outro ambiente retorna 404 not_found. As rotas de atribuição aceitam chave sandbox, restrita ao ambiente da chave.

Pessoas e papéis

GET /users exige team:read e lista os membros da Conta com id (igual a user_id), email, name e role: owner, admin ou member. O painel mostra dois papéis: owner e admin são Administrador (mesmos poderes; owner é o contato principal da Conta) e member é Operador. Use esse id em atribuições, retornos e responsáveis de CRM e Agenda. No painel, qualquer membro compartilha respostas com a equipe e altera critérios do Radar.

Pausar e retomar o agente de IA

POST /conversations/{id}/agent-control
{ "action": "pause" }

200
{ "data": { "conversation_id": "UUID-DA-CONVERSA", "paused": true } }

action é pause ou resume; o corpo é estrito. A rota exige agents:write e chave live. Também vale em canais atendidos por roteador: a pausa atinge o agente que o roteador escolheu para a conversa. Conversa inexistente retorna 404 not_found; falha temporária retorna 503 e pode ser repetida. Detalhes do agente em Agente de IA pela API.

O que a API ainda não oferece

  • Filtros das caixas do painel, como minhas, sem responsável, transferidas ao humano, adiadas ou arquivadas. Arquivamento e adiamento são consultados por conversa em /tools.
  • Contagem de não lidas e marcação de conversa como lida.
  • Rascunhos e respostas pessoais, que ficam restritos à sessão da pessoa no painel.

Respostas compartilhadas

MétodoCaminhoResultado
GET/saved-repliesLista com data e meta.
POST/saved-replies201 com data.
GET/saved-replies/{id}Resposta em data.
PATCH/saved-replies/{id}Resposta atualizada em data.
DELETE/saved-replies/{id}204, sem corpo.

A listagem aceita page, per_page (padrão 20, máximo 100), query (até 100 caracteres), customer_id e include_account=true. Sem Cliente, consulta todos os âmbitos compartilhados da Conta. Com UUID de Cliente, restringe a esse Cliente; include_account=true inclui também respostas gerais. customer_id=account lista somente as gerais. A resposta traz meta.page, per_page, total_pages e total_count, além dos headers de paginação.

Para criar, envie este corpo em POST /saved-replies:

{
  "title": "Resposta compartilhada",
  "body": "Olá {{primeiro_nome}}!",
  "shortcut": "ola"
}

title é obrigatório, até 80 caracteres; body, obrigatório, até 4096. As variáveis aceitas são {{nome}} e {{primeiro_nome}}. A API guarda o modelo: criar uma resposta não envia mensagem e não substitui variáveis por um contato.shortcut é opcional, até 40 caracteres, com letras sem acento, números, hífen ou sublinhado; a barra inicial é removida e letras viram minúsculas. customer_id é UUID do Cliente da Conta ou null para resposta geral. Omitir atalho ou Cliente equivale a null.

Cada resposta contém id, customer_id, owner_user_id (sempre null pela API), title, body, shortcut, created_at e updated_at. Campos como owner_user_id e shared não são aceitos no corpo.

Pela API, toda resposta criada é compartilhada com a equipe. No painel, qualquer pessoa da equipe cria respostas pessoais e compartilha, edita ou exclui as respostas da equipe.

Editar e excluir sem sobrescrever outra alteração

Leia a resposta e copie updated_at integralmente, preservando a precisão. Em PATCH, envie ao menos um campo editável junto de expected_updated_at. DELETE também exige um corpo JSON com essa versão. Os timestamps abaixo são exemplos; use o valor recebido na consulta.

PATCH /saved-replies/{id}
{
  "body": "Editada",
  "expected_updated_at": "2026-09-22T10:00:00.123456Z"
}

DELETE /saved-replies/{id}
{
  "expected_updated_at": "2026-09-22T10:01:00.123456Z"
}

Versão antiga retorna 409 version_conflict; releia e concilie a alteração. Atalho duplicado no mesmo âmbito retorna 409 shortcut_conflict. Cliente de outra Conta retorna 422 invalid_customer. Resposta pessoal ou de outra Conta retorna 404 not_found, inclusive nas tentativas de edição e exclusão. Cliente removido durante a gravação retorna 422 invalid_scope. UUID inválido retorna 422 invalid_id; corpo inválido, campos extras ou variável desconhecida retornam 422 invalid_saved_reply. Pesquisa inválida retorna 422 invalid_query.

Notas, retornos e organização

GET /conversations/{id}/tools exige inbox:read e retorna data com state, notes, reminders, page, per_page, notes_total e reminders_total. Notas e retornos usam a mesma página solicitada, cada lista com seu próprio total. page começa em 1; per_page tem padrão 20 e máximo 100. Não há meta externo neste endpoint.

state contém id, archived_at, snoozed_until e operator_version. As notas contêm autoria em author_user_id ou author_api_key_id, corpo, versão e timestamps. Retornos contêm assigned_user_id, corpo, due_at, status, completed_at, versão e timestamps. Ambos incluem id e conversation_id.

PATCH /conversations/{id}/tools exige inbox:write. Envie um objeto com operation e os campos da operação. O retorno vem em data: nota, retorno ou estado da conversa resultante. Datas devem ser ISO 8601 com fuso horário.

OperaçãoCampos adicionais
note_createbody, de 1 a 10000 caracteres.
note_updateid da nota, body e expected_version.
note_deleteid da nota e expected_version.
reminder_createbody (até 1000 caracteres), due_at; assigned_user_id opcional, membro da Conta ou null.
reminder_updateid, expected_version e campos opcionais body, due_at, assigned_user_id, status (pending, done ou cancelled).
archive, unarchive, unsnoozeexpected_version do estado da conversa.
snoozeexpected_version e until no futuro, no máximo um ano à frente.
PATCH /conversations/{id}/tools
{ "operation": "note_create", "body": "Nota interna" }

PATCH /conversations/{id}/tools
{ "operation": "archive", "expected_version": 1 }

Use a versão recebida em note.version ou reminder.version para alterar esses registros. Para arquivar ou adiar, use state.operator_version. Notas criadas pela API só podem ser editadas ou excluídas pela mesma chave autora; outra chave da Conta recebe 403 forbidden. Notas são internas e não geram mensagens para o contato. Arquivar ou adiar não renova a janela de envio do WhatsApp; uma nova mensagem recebida retira o arquivamento e o adiamento automaticamente.

Versão antiga ou alteração concorrente retorna 409 conflict. Registro inexistente, UUID de conversa inválido ou recurso de outra Conta retorna 404 not_found. Operação, campos, responsável ou data inválidos retornam 422 invalid_input. Não há operação de rascunho nessa API. Falhas de persistência retornam 500 database_error. Os erros seguem { error: { code, message } }.

CRM e Radar

Oportunidades, demandas, histórico, vínculos com conversas e o Radar de acompanhamento usam crm:read e crm:write, seguem o Funil do plano e aceitam chaves sandbox restritas ao ambiente. Campos, limites, motivos do Radar e erros estão em CRM e Radar pela API. Os retornos pendentes criados em /tools também aparecem no Radar.

Agenda e Google Calendar

Compromissos, disponibilidade, serviços, jornadas e exceções usam appointments:read e appointments:write; a sincronização com Google Calendar e Meet usa calendar:read e calendar:write. As duas exigem chave live. O contrato completo está em Agenda e Google Calendar pela API.

Os erros comuns de chave, escopo, limite e acesso ao produto continuam descritos em Autenticação. Consulte a referência /v1 para integrar esses recursos com as demais rotas.