BoaVoz
Documentação · API

Contatos e leads

Sincronize os contatos com o seu sistema, troque as etiquetas, mande as datas das réguas, informe a idade conferida por você, leia os leads e atenda o pedido do titular para apagar os dados.

Permissão da chavecontactsPacoteIntegrações (R$ 49 por mês, por conta). Sem ele, a API responde 403 plan_not_allowed.
RotaO que faz
GET /v1/contactsOs contatos, na ordem da última alteração (para sincronizar).
PUT /v1/contacts/{contact}/tagsTroca as etiquetas do contato.
PATCH /v1/contacts/{contact}Grava o aniversário, a última visita e o próximo horário (as datas das réguas).
PUT /v1/contacts/{contact}/ageA empresa informa a idade que conferiu.
GET /v1/leadsUm lead por contato, com o histórico de pedidos.
DELETE /v1/contacts/{contact}?bot_id=Pedido do titular: apaga os dados do contato.

{contact} é o endereço do contato (ctc_…, phone:…, wa:…, ig:… ou ext:…).

GET/v1/contacts

Na ordem da última alteração: guarde o updated_at do último e use em since na próxima vez. consent.marketing é o aceite de novidades no WhatsApp (none, granted, declined ou revoked); consent.opted_out, o que a pessoa pediu para não receber (marketing, utility ou all); age_confirmed, o 18+ (null: ninguém perguntou); birthday, last_visit_at e appointment_at, as datas das réguas.

Listar os contatos (para sincronizar)
curl "https://boavoz.com/api/v1/contacts?limit=20" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY"
Resposta · 200
{
  "data": [
    {
      "id": "ctc_9a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
      "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "channel": "whatsapp",
      "name": "Ruan",
      "email": null,
      "phone": "5511999990000",
      "whatsapp_user_id": null,
      "instagram_id": null,
      "external_id": null,
      "tags": [
        "vip"
      ],
      "consent": {
        "marketing": "granted",
        "opted_out": []
      },
      "age_confirmed": null,
      "birthday": "10-21",
      "last_visit_at": "2026-10-05T15:00:00.000Z",
      "appointment_at": null,
      "dates": {
        "renovacao_do_plano": "2027-03-10"
      },
      "first_inbound_at": "2026-10-02T13:10:44.000Z",
      "last_inbound_at": "2026-10-19T14:58:02.117Z",
      "created_at": "2026-10-02T13:10:44.000Z",
      "updated_at": "2026-10-19T14:58:02.117Z"
    }
  ],
  "next_cursor": null
}
ParâmetroRegraErro
limit, cursorPaginação: limit de 1 a 100 (padrão 50) e o next_cursor anterior.400 limit, cursor
bot_idSó os contatos deste chatbot.403 forbidden_scope
channelwidget, whatsapp ou instagram.400 channel
tagSó os com esta etiqueta (até 30 caracteres).400 tag
sinceSó os alterados desde a data (ISO 8601).400 since

PUT/v1/contacts/{contact}/tags

Troca todas as etiquetas (lista vazia apaga). Com ext:, vale para todos os contatos do chatbot com aquele id externo.

Trocar as etiquetas
curl -X PUT "https://boavoz.com/api/v1/contacts/ctc_9a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d/tags" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "tags": [
    "vip",
    "postman"
  ]
}'
Resposta · 200
{
  "data": [
    {
      "id": "ctc_9a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
      "tags": [
        "vip",
        "postman"
      ]
    }
  ]
}
CampoRegraErro
bot_idObrigatório: o chatbot do contato.403 forbidden_scope
tagsLista de textos, até 20 (vírgula e ponto e vírgula viram espaço). Contato que não existe: 404.400 tags

PATCH/v1/contacts/{contact}

As datas que as réguas do WhatsApp usam: o aniversário, a última visita ou compra (“faz tempo que você não vem” e o pós-atendimento) e o próximo horário marcado (o lembrete antes do horário). O campo que não vem não muda; null apaga. Pelo telefone (phone:…), cria o contato do WhatsApp que ainda não existe: o horário costuma chegar antes da primeira mensagem. Com ext:, vale para todos os contatos do chatbot com aquele id externo. A resposta traz os contatos alterados.

Gravar o aniversário, a última visita e o próximo horário
curl -X PATCH "https://boavoz.com/api/v1/contacts/phone:5511999990000" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "birthday": "10-21",
  "last_visit_at": "2026-10-05",
  "appointment_at": "2026-12-20T14:30:00-03:00"
}'
Resposta · 200
{
  "data": [
    {
      "id": "ctc_9a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d",
      "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "channel": "whatsapp",
      "name": "Ruan",
      "email": null,
      "phone": "5511999990000",
      "whatsapp_user_id": null,
      "instagram_id": null,
      "external_id": null,
      "tags": [
        "vip",
        "postman"
      ],
      "consent": {
        "marketing": "granted",
        "opted_out": []
      },
      "age_confirmed": null,
      "birthday": "10-21",
      "last_visit_at": "2026-10-05T15:00:00.000Z",
      "appointment_at": "2026-12-20T17:30:00.000Z",
      "dates": {
        "renovacao_do_plano": "2027-03-10"
      },
      "first_inbound_at": "2026-10-02T13:10:44.000Z",
      "last_inbound_at": "2026-10-19T14:58:02.117Z",
      "created_at": "2026-10-02T13:10:44.000Z",
      "updated_at": "2026-10-20T15:00:00.000Z"
    }
  ]
}
CampoRegraErro
bot_idObrigatório: o chatbot do contato.403 forbidden_scope
birthdayMês e dia, MM-DD (ex.: 10-21). A data inteira (AAAA-MM-DD) também vale, mas o ano não é guardado.400 birthday
last_visit_atA última visita ou compra: data (AAAA-MM-DD) ou data e hora ISO 8601 com fuso. Não pode ser no futuro.400 last_visit_at
appointment_atO próximo horário marcado: data e hora ISO 8601 com fuso (ex.: 2026-12-20T14:30:00-03:00), até um ano à frente.400 appointment_at
datesAs datas novas das suas réguas (régua personalizada), pela chave de cada uma: { "renovacao_do_plano": "2027-03-10" }. A data é AAAA-MM-DD; null apaga. A chave nasce com a régua que tem a data nova, no painel; as outras chaves do contato ficam.400 dates.<chave>
Nenhum dos quatroMande pelo menos um.400 birthday
Contato que não existeCom ctc_, wa:, ig: ou ext:: o contato precisa existir.404 not_found

PUT/v1/contacts/{contact}/age

Para quem vende bebida alcoólica ou remédio: o BoaVoz só mostra esses itens para quem tem 18 anos confirmados. Um “Não” dado pela pessoa no chat sempre vence o que a empresa informar (age_confirmed_source chat). A data de nascimento daqui nunca é guardada; para a régua do aniversário, mande o dia e o mês em birthday.

A empresa confirma a idade
curl -X PUT "https://boavoz.com/api/v1/contacts/phone:5511999990000/age" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "age_verified": true,
  "origin": "Teste pelo Postman"
}'
Resposta · 200
{
  "age_confirmed": true,
  "age_confirmed_source": "company"
}
CampoRegraErro
bot_idObrigatório.403 forbidden_scope
age_verified ou birth_dateage_verified true ou false, ou birth_date (AAAA-MM-DD, no passado). Com os dois, eles precisam bater.400 age_verified, birth_date
originObrigatório: como a idade foi conferida (3 a 300 caracteres).400 origin

GET/v1/leads

Um lead por contato em cada chatbot, do mais antigo para o mais novo: nome, telefone, e-mail, o pedido mais recente (notes) e o histórico (requests). Filtros: bot_id, channel, since (criados desde a data) e updated_since (os que mudaram desde a data: pedido novo ou contato); o webhook lead.updated avisa na hora.

Listar os leads
curl "https://boavoz.com/api/v1/leads?limit=20" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY"
Resposta · 200
{
  "data": [
    {
      "id": "lead_7f3e2d1c-0b9a-4c8d-9e7f-6a5b4c3d2e1f",
      "bot_id": "bot_7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "conversation_id": "conv_0e8f5a3c-2b1d-4c6e-9f7a-1d2c3b4a5e6f",
      "channel": "whatsapp",
      "name": "Ana Souza",
      "phone": "5511988887777",
      "email": "ana@exemplo.com.br",
      "instagram": null,
      "notes": "Quer orçamento para 30 pizzas no sábado.",
      "requests": [
        {
          "created_at": "2026-10-19T15:10:00.000Z",
          "channel": "whatsapp",
          "conversation_id": "conv_0e8f5a3c-2b1d-4c6e-9f7a-1d2c3b4a5e6f",
          "text": "Quer orçamento para 30 pizzas no sábado."
        }
      ],
      "created_at": "2026-10-19T15:10:00.000Z",
      "last_request_at": "2026-10-19T15:10:00.000Z",
      "updated_at": "2026-10-19T15:10:00.000Z"
    }
  ],
  "next_cursor": null
}

DELETE/v1/contacts/{contact}?bot_id=

Para o pedido do titular (LGPD) que você já confirmou: apaga as conversas, os arquivos, os leads e a ficha do contato, põe o número na lista de supressão e emite o webhook contact.deleted. Responde 202 com o request_id na hora; a exclusão roda logo depois e aparece em Segurança, no painel.

Apagar os dados do contato (pedido do titular)
curl -X DELETE "https://boavoz.com/api/v1/contacts/phone:5511999990000?bot_id=bot_7c9e6679-7425-40de-944b-e07fc1f90ae7" \
  -H "Authorization: Bearer $BOAVOZ_API_KEY"
Resposta · 202
{
  "request_id": "dsr_1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f"
}
Não tem volta
Depois da exclusão, mandar modelo para esse número volta 422 contact_suppressed, e nada do contato pode ser recuperado.