# DoneTalk API (Português): Desenvolvedores # API do DoneTalk A API deixa o seu sistema (ERP, CRM, site, automação) fazer no DoneTalk o que se faz na tela: criar e disparar campanhas de WhatsApp, cadastrar e atualizar contatos, mandar mensagens, acompanhar e concluir atendimentos, marcar horários e receber avisos de tudo o que acontece. - **Endereço:** `https://api.donetalk.com/v1/c/{empresa}`, onde `{empresa}` é o identificador da sua empresa no DoneTalk. - **Formato:** JSON, datas em ISO 8601 (UTC), ids em UUID, valores em dinheiro em micros (1.000.000 = 1 unidade da moeda). - **Especificação completa:** [OpenAPI](https://api.donetalk.com/v1/openapi.json?lang=pt), para gerar código ou importar no Postman. ## Primeiros passos 1. Um administrador cria a chave em **Configurações › API** no DoneTalk e marca o que ela pode fazer. Para começar sem risco, escolha **Teste**: ela simula tudo e não envia nada. 2. Confira a chave: ```bash curl https://api.donetalk.com/v1/c/{empresa}/me \ -H "Authorization: Bearer $DONETALK_KEY" ``` 3. Crie uma campanha com a lista de contatos na própria chamada, revise o custo e dispare. O guia [Campanhas, do começo ao fim](/desenvolvedores/campanhas/) mostra cada passo. 4. Cadastre um endereço do seu sistema para receber os [avisos](/desenvolvedores/avisos/): entregue, lida, respondida, atendimento concluído com o desfecho. ## Experimente agora, sem conta A empresa de demonstração `demo` aceita a chave de teste pública abaixo. Tudo é simulado: as respostas têm o formato real, com dados de exemplo, e nada é gravado ou enviado. ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl -X POST https://api.donetalk.com/v1/c/demo/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Primeira campanha", "audience": {"kind": "contacts", "people": [{"phone": "+5548999990001", "name": "Ana"}]}}' ``` ## O que a API cobre | Área | O que dá para fazer | | ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | [Campanhas](/desenvolvedores/referencia/campaigns/) | criar, revisar custo e regras, testar, disparar ou agendar, pausar, retomar, cancelar, reenviar falhas, ver cada destinatário e os resultados | | [Segmentos](/desenvolvedores/referencia/segments/) | grupos de contatos por condições, contar e buscar | | [Contatos](/desenvolvedores/referencia/contacts/) | criar, atualizar ou importar até 1.000 por vez, etiquetas, consentimento, fichas de contexto, apagar a pedido do titular | | [Campos](/desenvolvedores/referencia/contact-fields/) | ver e criar os campos dos contatos | | [Modelos](/desenvolvedores/referencia/templates/) | os modelos aprovados pela Meta, com variáveis e botões | | [Mensagens](/desenvolvedores/referencia/messages/) e [atendimentos](/desenvolvedores/referencia/conversations/) | mandar um modelo para um telefone, texto e arquivos na janela de 24 h, concluir com desfecho | | [Números, equipes e etiquetas](/desenvolvedores/referencia/numbers-teams-and-tags/) | para escolher o número que envia e a equipe que recebe as respostas | | [Agenda](/desenvolvedores/referencia/scheduling/) | horários livres, marcar, remarcar e cancelar | | [Avisos](/desenvolvedores/referencia/webhooks/) | criar e acompanhar os endereços que recebem os eventos | ## Antes de ir para produção - Use uma chave por sistema, só com os escopos de que ele precisa ([Chaves e escopos](/desenvolvedores/chaves-e-escopos/)). - Mande `Idempotency-Key` em criações e envios e respeite o limite de 600 chamadas por minuto ([Erros e limites](/desenvolvedores/erros-e-limites/)). - Confira a assinatura de cada aviso ([Avisos](/desenvolvedores/avisos/)). --- # Chaves e escopos ## Criar uma chave Em **Configurações › API**, um administrador cria a chave e escolhe: - **Nome:** o sistema que vai usá-la (ex.: “ERP Captei”). - **Ambiente:** **Produção** age de verdade; **Teste** simula tudo ([Modo teste](/desenvolvedores/modo-teste/)). - **O que a chave pode fazer:** os escopos abaixo. Uma chamada fora dos escopos da chave volta `403 insufficient_scope`, dizendo em `details.required` quais escopos servem. - **Disparar campanhas sem esperar aprovação:** sem isso, as campanhas desta chave seguem a regra de aprovação da empresa (o orçamento vale sempre). - **Vale até** e **só destes endereços IP**, opcionais. A chave inteira aparece uma única vez, na criação. Guarde-a como uma senha. Chaves de produção começam com `dt_live_`, de teste com `dt_test_`. ## Autenticar Mande a chave em toda chamada: ```http Authorization: Bearer dt_live_... ``` `Authorization: ApiKey dt_live_...` também funciona. A empresa vem do endereço (`/v1/c/{empresa}/...`) e precisa ser a da chave. ## Escopos | Grupo | Escopo | O que permite | |---|---|---| | Campanhas | `campaigns:read` | Ver campanhas e resultados | | Campanhas | `campaigns:write` | Criar e editar rascunhos | | Campanhas | `campaigns:send` | Disparar, pausar e cancelar | | Contatos | `contacts:read` | Ver contatos e os valores dos campos | | Contatos | `contacts:write` | Criar e atualizar contatos | | Contatos | `fields:read` | Ver a lista de campos | | Contatos | `fields:write` | Criar campos | | Contatos | `contacts:delete` | Apagar dados de contatos (LGPD) | | Modelos | `templates:read` | Ver modelos | | Modelos | `templates:write` | Criar e enviar modelos para a Meta | | Mensagens e atendimentos | `messages:send_template` | Enviar modelos | | Mensagens e atendimentos | `messages:send_text` | Enviar texto e arquivos (janela de 24h) | | Mensagens e atendimentos | `conversations:read` | Ver atendimentos e mensagens | | Mensagens e atendimentos | `conversations:write` | Concluir e reabrir atendimentos | | Fluxos e agenda | `flows:start` | Iniciar fluxos | | Fluxos e agenda | `appointments:read` | Ver agendamentos | | Fluxos e agenda | `appointments:write` | Marcar, remarcar e cancelar agendamentos | | Outros | `webhooks:manage` | Gerenciar avisos (webhooks) | | Outros | `reports:read` | Ver relatórios e custos | | Outros | `workspace:read` | Ver números, equipes e etiquetas | | Outros | `integrations:outboundpro` | Conectar ao OutboundPro Conversas | ## Chaves antigas Chaves criadas antes dos escopos (`dsf_live_...`) continuam funcionando com o acesso de integração que tinham. Ao escolher escopos para uma delas, ela passa a valer só para eles. ## Segurança - Uma chave por sistema, com o mínimo de escopos. - Se uma chave vazar, revogue em Configurações › API: ela para na hora. - Criação, edição e revogação ficam na Auditoria, com quem fez. --- # Modo teste Uma chave de **Teste** (`dt_test_...`) responde como a de produção, com dados de exemplo. Nada é gravado, nenhuma mensagem sai e nada é cobrado. - Cada chamada é conferida com as mesmas regras da produção: um campo errado dá o mesmo `422 validation_failed`. - A resposta tem o mesmo formato da real, com `"test": true` e o cabeçalho `DoneTalk-Test: true`. - `GET /me` responde de verdade, para conferir a chave. - Escopos, limite de chamadas e `Idempotency-Key` valem como em produção. ## Simular um erro Mande o cabeçalho `DoneTalk-Simulate` com o código do erro para receber exatamente a resposta que a produção daria: ```bash curl -X POST https://api.donetalk.com/v1/c/demo/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "DoneTalk-Simulate: template_not_approved" \ -H "Content-Type: application/json" \ -d '{"name": "Teste"}' ``` Códigos aceitos: `unauthorized`, `api_key_invalid`, `api_key_expired`, `api_key_address_not_allowed`, `insufficient_scope`, `not_available_to_api_keys`, `not_available_to_test_keys`, `permission_denied`, `integration_template_only`, `not_found`, `campaign_not_found`, `contact_not_found`, `validation_failed`, `campaign_not_editable`, `template_not_approved`, `campaign_audience_empty`, `contact_exists`, `window_closed`, `idempotency_key_reused`, `idempotency_in_progress`, `rate_limited`, `internal_error`. ## Telefones mágicos Em qualquer campo de telefone, estes números provocam um comportamento conhecido: | Telefone | O que acontece | |---|---| | `+550000000400` | `validation_failed` (422) | | `+550000000404` | `contact_not_found` (404) | | `+550000000409` | `contact_exists` (409) | | `+550000000429` | `rate_limited` (429) | | `+550000000500` | `internal_error` (500) | | `+550000000131` | message.failed / campaign.recipient.failed: `131026` | | `+550000000470` | message.failed / campaign.recipient.failed: `131047` | ## Avisos de teste Um envio na chave de teste (mensagem, campanha) manda aos avisos da empresa a sequência que a produção mandaria, alguns segundos depois: enviada, entregue, lida e, numa campanha, respondida e concluída. Com um telefone mágico de falha, chega a falha. O envelope traz `"test": true`. ## Empresa de demonstração Para testar sem conta, use a empresa `demo` com a chave pública: ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl https://api.donetalk.com/v1/c/demo/me -H "Authorization: Bearer $DONETALK_KEY" ``` Ela só simula: não há como agir de verdade com ela. --- # Erros, limites e boas práticas ## Formato dos erros Todo erro volta assim: ```json { "error": "validation_failed", "message": "Algum campo veio errado. `details` diz qual e por quê.", "details": { "name": ["Required"] }, "request_id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" } ``` - `error` é o código estável: é nele que o seu sistema decide o que fazer. - `message` explica, no idioma do cabeçalho `Accept-Language` (português, inglês ou espanhol; inglês se não vier). - `request_id` identifica a chamada: cite-o ao falar com o suporte. Você pode mandar o seu em `X-Request-Id`. | HTTP | Código | O que fazer | |---|---|---| | 401 | `unauthorized` | Falta a chave. Envie Authorization: Bearer . | | 401 | `api_key_invalid` | Chave inválida ou revogada. Confira a chave ou crie outra em Configurações › API. | | 401 | `api_key_expired` | A chave passou da validade. Crie outra em Configurações › API. | | 403 | `api_key_address_not_allowed` | Esta chave não aceita chamadas deste endereço IP. Inclua o endereço na chave. | | 403 | `insufficient_scope` | A chave não tem o escopo desta chamada. `details.required` diz quais servem. | | 403 | `not_available_to_api_keys` | Esta chamada não faz parte da API pública. | | 403 | `not_available_to_test_keys` | Esta chamada não tem modo teste: use uma chave de produção. | | 403 | `permission_denied` | A chave não pode fazer isto. | | 403 | `integration_template_only` | Texto e arquivos pedem o escopo messages:send_text; sem ele, só modelos aprovados. | | 404 | `not_found` | Não encontrado. | | 404 | `campaign_not_found` | Campanha não encontrada nesta empresa. | | 404 | `contact_not_found` | Contato não encontrado nesta empresa. | | 422 | `validation_failed` | Algum campo veio errado. `details` diz qual e por quê. | | 409 | `campaign_not_editable` | A campanha já saiu do rascunho; só um rascunho pode ser editado ou disparado. | | 409 | `template_not_approved` | O modelo ainda não foi aprovado pela Meta. Espere a aprovação ou escolha outro. | | 409 | `campaign_audience_empty` | Ninguém do público pode receber a campanha. Veja os motivos na prévia do público. | | 409 | `contact_exists` | Já existe um contato com este telefone. `details.contactId` diz qual. | | 409 | `window_closed` | A janela de 24 horas está fechada: só um modelo aprovado pode iniciar a conversa. | | 409 | `idempotency_key_reused` | Esta Idempotency-Key já foi usada com outro pedido. Use uma chave nova por pedido. | | 409 | `idempotency_in_progress` | O primeiro pedido com esta Idempotency-Key ainda está em andamento. Tente em instantes. | | 429 | `rate_limited` | Limite de 600 chamadas por minuto. Espere os segundos de Retry-After. | | 500 | `internal_error` | Erro do nosso lado. Já fomos avisados; tente de novo com o mesmo request_id se persistir. | ## Limite de chamadas Cada chave pode fazer 600 chamadas por minuto. Toda resposta diz onde você está: ```http RateLimit-Limit: 600 RateLimit-Remaining: 587 RateLimit-Reset: 41 ``` Passou do limite, a resposta é `429 rate_limited` com `Retry-After` (segundos). Espere esse tempo e tente de novo. O disparo de uma campanha não conta: quem envia é o DoneTalk, no ritmo que a Meta permite para o número. ## Repetir sem duplicar Mande `Idempotency-Key` (até 200 letras, números, `_ . : -`) em criações e envios. Se a rede cair e você mandar de novo a mesma chamada com a mesma chave em até 24 horas, recebe a primeira resposta, com `Idempotent-Replayed: true`, e nada é feito duas vezes. A mesma chave com outro pedido volta `409 idempotency_key_reused`. ```http Idempotency-Key: pedido-88213-campanha ``` ## Paginação - **Campanhas:** `limit` e `cursor`; a resposta traz `nextCursor` (null na última página). - **Contatos:** `limit` e `before` (o `lastActivityAt` do último da página). - **Destinatários de uma campanha:** `limit` e `offset`, ou `format=csv` para tudo. ## Versões A v1 só ganha coisas novas: campos e chamadas a mais, nunca mudança no que já existe. Ignore campos que você não conhece. Se um dia for preciso mudar algo, nasce a v2, e a v1 continua por 12 meses, com aviso. --- # Avisos (webhooks) O DoneTalk avisa o seu sistema do que acontece, com um POST assinado para um endereço seu: uma campanha começou ou terminou, uma mensagem foi entregue ou lida, um contato respondeu, um atendimento foi concluído com o desfecho. ## Cadastrar um endereço Em **Configurações › Integrações › Webhooks de saída**, ou pela API com o escopo `webhooks:manage`: ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/webhooks \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{"url": "https://seu-sistema.com/donetalk/avisos", "events": ["campaign.completed", "campaign.recipient.replied", "conversation.closed"]}' ``` A resposta traz o `secret` uma única vez: guarde para conferir as assinaturas. ## O que chega ```http POST /donetalk/avisos HTTP/1.1 Content-Type: application/json User-Agent: DoneTalk-Webhooks/1.0 DoneTalk-Signature: t=1792756800,v1=5f0c… X-DoneTalk-Event: conversation.closed X-DoneTalk-Delivery: 01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f ``` ```json { "id": "01a3e4f5-…", "type": "conversation.closed", "occurredAt": "2026-10-24T12:20:41.000Z", "customerId": "01a0c0de-…", "data": { "...": "o conteúdo do evento" } } ``` Avisos de uma chave de teste trazem `"test": true`. ## Conferir a assinatura `DoneTalk-Signature` traz `t` (o horário do envio, em segundos) e `v1`, o HMAC SHA-256 de `"."` com o seu `secret`. Recuse avisos com `t` de mais de 5 minutos atrás: assim ninguém reenvia um aviso antigo. ```js import crypto from "node:crypto"; function avisoValido(rawBody, header, secret) { const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("="))); if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; const esperado = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex"); return crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(v1)); } ``` ```python import hmac, hashlib, time def aviso_valido(raw_body: bytes, header: str, secret: str) -> bool: parts = dict(p.split("=", 1) for p in header.split(",")) if abs(time.time() - int(parts["t"])) > 300: return False esperado = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(esperado, parts["v1"]) ``` O cabeçalho antigo `x-donetalk-signature` (`sha256=` + HMAC do corpo, sem horário) segue junto até 21/01/2027. ## Responder e tentativas Responda `2xx` em até 10 segundos; faça o trabalho pesado depois. Sem `2xx`, o DoneTalk tenta de novo em 1 min, 5 min, 30 min, 2 h e 12 h. Depois de 20 falhas seguidas o endereço aparece como “Com falhas” (continua recebendo). Um mesmo aviso pode chegar mais de uma vez: use o `id` para não processar duas vezes. A ordem de chegada não é garantida: use `occurredAt`. ## Eventos | Evento | Quando chega | |---|---| | `conversation.opened` | Um atendimento começou (o contato escreveu ou clicou num anúncio). | | `conversation.closed` | Um atendimento foi concluído, com o desfecho, quem concluiu (pessoa, assistente de IA ou regra automática), a anotação de encerramento, o contato, a equipe, as etiquetas, quanto durou e a campanha de origem. | | `conversation.assigned` | Um atendimento foi atribuído a uma pessoa. | | `conversation.transferred` | Um atendimento passou para outra equipe ou pessoa. | | `conversation.reopened` | Um atendimento concluído foi reaberto. | | `contact.updated` | Os dados de um contato mudaram. | | `contact.consent_changed` | O contato aceitou ou recusou receber mensagens de uma finalidade (marketing, por exemplo). | | `message.received` | O contato mandou uma mensagem. | | `message.sent` | Uma mensagem nossa saiu para o WhatsApp. | | `message.delivered` | Uma mensagem chegou ao celular do contato. | | `message.read` | O contato leu uma mensagem. | | `message.failed` | Uma mensagem não pôde ser entregue; `error.code` é o código da Meta. | | `flow.event` | Um fluxo chegou a um bloco “Registrar evento”, com o nome e os dados que o bloco define. | | `appointment.booked` | Um agendamento foi marcado. | | `appointment.rescheduled` | Um agendamento mudou de horário. | | `appointment.cancelled` | Um agendamento foi cancelado. | | `appointment.confirmed` | O contato confirmou o agendamento. | | `appointment.attended` | O contato compareceu. | | `appointment.no_show` | O contato faltou. | | `campaign.started` | A campanha começou a enviar; a lista foi fechada. | | `campaign.paused` | A campanha pausou: por uma pessoa, pela API ou por uma regra (modelo pausado, qualidade baixa, muitos pedidos para sair, orçamento). | | `campaign.resumed` | A campanha voltou a enviar. | | `campaign.completed` | A campanha terminou de enviar, com os totais. | | `campaign.cancelled` | A campanha foi cancelada. | | `campaign.recipient.sent` | A mensagem da campanha saiu para um contato. | | `campaign.recipient.delivered` | A mensagem da campanha chegou ao contato. | | `campaign.recipient.read` | O contato leu a mensagem da campanha. | | `campaign.recipient.replied` | O contato respondeu à campanha (a primeira resposta), por texto ou tocando num botão. | | `campaign.recipient.failed` | A mensagem da campanha falhou para um contato; `errorCode` é o código da Meta. | | `campaign.recipient.opted_out` | O contato pediu para não receber mais campanhas (botão “Parar promoções” ou recusa na Meta). | ## Exemplos de cada evento ### conversation.opened Um atendimento começou (o contato escreveu ou clicou num anúncio). ```json { "id": "01a3e4f5-…", "type": "conversation.opened", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "handler": "flow", "source": "inbound" } } ``` ### conversation.closed Um atendimento foi concluído, com o desfecho, quem concluiu (pessoa, assistente de IA ou regra automática), a anotação de encerramento, o contato, a equipe, as etiquetas, quanto durou e a campanha de origem. ```json { "id": "01a3e4f5-…", "type": "conversation.closed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "outcome": "converted", "isSuccess": true, "closedBy": { "kind": "member", "id": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "name": "Tayomara Batista" }, "actorKind": "member", "openedAt": "2026-10-24T12:00:04.000Z", "firstResponseAt": "2026-10-24T12:05:10.000Z", "messagesIn": 6, "messagesOut": 7, "outcomeLabel": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "outcomeCategory": "success", "note": "Fechou o plano anual com o cupom ANA10.", "contact": { "name": "Ana Souza", "phone": "5548999990001" }, "team": { "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "name": "Vendas" }, "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" } } ], "durationSeconds": 1237, "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" } } ``` ### conversation.assigned Um atendimento foi atribuído a uma pessoa. ```json { "id": "01a3e4f5-…", "type": "conversation.assigned", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "reason": "distribution", "previousAssigneeId": null, "actorKind": "system" } } ``` ### conversation.transferred Um atendimento passou para outra equipe ou pessoa. ```json { "id": "01a3e4f5-…", "type": "conversation.transferred", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": null, "previousTeamId": null, "previousAssigneeId": null, "previousHandler": "flow", "actorKind": "flow", "reason": "Gestor de conta: Tayomara Batista" } } ``` ### conversation.reopened Um atendimento concluído foi reaberto. ```json { "id": "01a3e4f5-…", "type": "conversation.reopened", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" } } ``` ### contact.updated Os dados de um contato mudaram. ```json { "id": "01a3e4f5-…", "type": "contact.updated", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "changes": [ "fields", "displayName" ] } } ``` ### contact.consent_changed O contato aceitou ou recusou receber mensagens de uma finalidade (marketing, por exemplo). ```json { "id": "01a3e4f5-…", "type": "contact.consent_changed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channel": "whatsapp", "purpose": "marketing", "status": "opted_out", "source": "keyword", "occurredAt": "2026-10-24T12:06:00.000Z" } } ``` ### message.received O contato mandou uma mensagem. ```json { "id": "01a3e4f5-…", "type": "message.received", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "channelId": "01a0cccc-0000-7000-8000-000000000002", "type": "text" } } ``` ### message.sent Uma mensagem nossa saiu para o WhatsApp. ```json { "id": "01a3e4f5-…", "type": "message.sent", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "providerMessageId": "wamid.HBgMNTU0ODk5OTk5MDAwMRUCABEYEjE=" } } ``` ### message.delivered Uma mensagem chegou ao celular do contato. ```json { "id": "01a3e4f5-…", "type": "message.delivered", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "delivered", "occurredAt": "2026-10-24T12:00:06.000Z" } } ``` ### message.read O contato leu uma mensagem. ```json { "id": "01a3e4f5-…", "type": "message.read", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "read", "occurredAt": "2026-10-24T12:03:51.000Z" } } ``` ### message.failed Uma mensagem não pôde ser entregue; `error.code` é o código da Meta. ```json { "id": "01a3e4f5-…", "type": "message.failed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "failed", "occurredAt": "2026-10-24T12:00:06.000Z", "error": { "code": "131026", "detail": "Message undeliverable" } } } ``` ### flow.event Um fluxo chegou a um bloco “Registrar evento”, com o nome e os dados que o bloco define. ```json { "id": "01a3e4f5-…", "type": "flow.event", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "name": "lead.qualified", "data": { "plano": "anual", "origem": "site" } } } ``` ### appointment.booked Um agendamento foi marcado. ```json { "id": "01a3e4f5-…", "type": "appointment.booked", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.rescheduled Um agendamento mudou de horário. ```json { "id": "01a3e4f5-…", "type": "appointment.rescheduled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 1, "previousStartsAt": "2026-10-27T12:00:00.000Z", "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.cancelled Um agendamento foi cancelado. ```json { "id": "01a3e4f5-…", "type": "appointment.cancelled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "cancelled", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": "2026-10-26T18:00:00.000Z", "cancelledByKind": "contact", "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.confirmed O contato confirmou o agendamento. ```json { "id": "01a3e4f5-…", "type": "appointment.confirmed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "confirmed", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": "2026-10-26T14:00:00.000Z", "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.attended O contato compareceu. ```json { "id": "01a3e4f5-…", "type": "appointment.attended", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "attended", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### appointment.no_show O contato faltou. ```json { "id": "01a3e4f5-…", "type": "appointment.no_show", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "no_show", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### campaign.started A campanha começou a enviar; a lista foi fechada. ```json { "id": "01a3e4f5-…", "type": "campaign.started", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "running", "audience": 1240, "skipped": 24, "startedAt": "2026-10-24T12:00:00.000Z" } } ``` ### campaign.paused A campanha pausou: por uma pessoa, pela API ou por uma regra (modelo pausado, qualidade baixa, muitos pedidos para sair, orçamento). ```json { "id": "01a3e4f5-…", "type": "campaign.paused", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "paused", "reason": "optout_rate", "by": "system" } } ``` ### campaign.resumed A campanha voltou a enviar. ```json { "id": "01a3e4f5-…", "type": "campaign.resumed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "running", "by": "api_key" } } ``` ### campaign.completed A campanha terminou de enviar, com os totais. ```json { "id": "01a3e4f5-…", "type": "campaign.completed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "completed", "totals": { "audience": 1216, "sent": 1216, "delivered": 1198, "read": 874, "replied": 141, "failed": 18, "skipped": 24, "optedOut": 6 } } } ``` ### campaign.cancelled A campanha foi cancelada. ```json { "id": "01a3e4f5-…", "type": "campaign.cancelled", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "status": "cancelled", "by": "member" } } ``` ### campaign.recipient.sent A mensagem da campanha saiu para um contato. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.sent", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:00:04.000Z" } } ``` ### campaign.recipient.delivered A mensagem da campanha chegou ao contato. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.delivered", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:00:06.000Z" } } ``` ### campaign.recipient.read O contato leu a mensagem da campanha. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.read", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "at": "2026-10-24T12:03:51.000Z" } } ``` ### campaign.recipient.replied O contato respondeu à campanha (a primeira resposta), por texto ou tocando num botão. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.replied", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "buttonIndex": 0, "text": "Quero o cupom" } } ``` ### campaign.recipient.failed A mensagem da campanha falhou para um contato; `errorCode` é o código da Meta. ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.failed", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "phone": "5548999990001", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "errorCode": "131026" } } ``` ### campaign.recipient.opted_out O contato pediu para não receber mais campanhas (botão “Parar promoções” ou recusa na Meta). ```json { "id": "01a3e4f5-…", "type": "campaign.recipient.opted_out", "occurredAt": "2026-10-24T12:04:02.000Z", "customerId": "01a0c0de-…", "data": { "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "via": "button" } } ``` --- # Campanhas, do começo ao fim Uma campanha manda um modelo aprovado pela Meta, de um número seu, para uma lista de contatos, e leva as respostas para quem você escolher (uma equipe, um fluxo ou um assistente de IA). Este guia faz uma campanha inteira pela API. Teste tudo antes com a [chave de demonstração](/desenvolvedores/modo-teste/). ## 1. O que você precisa saber antes ```bash curl https://api.donetalk.com/v1/c/{empresa}/channels -H "Authorization: Bearer $DONETALK_KEY" curl https://api.donetalk.com/v1/c/{empresa}/templates -H "Authorization: Bearer $DONETALK_KEY" curl https://api.donetalk.com/v1/c/{empresa}/teams -H "Authorization: Bearer $DONETALK_KEY" ``` - **Número (`channelId`):** de onde a mensagem sai. - **Modelo (`templateId`):** um modelo `approved` da mesma conta do número. As variáveis aparecem no texto como `{{1}}`, `{{2}}`. - **Equipe (`reply.id`):** quem recebe as respostas. ## 2. Criar o rascunho, com a lista ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Idempotency-Key: reativacao-2026-10" \ -H "Content-Type: application/json" \ -d '{ "name": "Reativação · outubro", "channelId": "…", "templateId": "…", "variables": [ { "slot": "body.1", "source": "first_name", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper" } ], "audience": { "kind": "contacts", "people": [ { "phone": "+5548999990001", "name": "Ana Souza", "values": { "cupom": "ana10" } }, { "phone": "+5548999990002", "name": "Bruno Lima", "values": { "cupom": "bru15" } } ] }, "reply": { "kind": "team", "id": "…" }, "startAt": "2026-10-24T12:00:00.000Z" }' ``` - **Público:** `people` traz telefone, nome e valores de cada pessoa (até 20 mil; cada telefone vira um contato, criado ou atualizado, o que pede também o escopo `contacts:write`). Também dá para usar contatos já cadastrados (`contactIds`), um segmento (`{"kind": "segment", "segmentId": "…"}`) ou um filtro. - **Variáveis:** cada `{{n}}` do modelo vem de `name`, `first_name`, `phone`, um campo do contato (`field.`), um valor da lista (`value.`) ou um texto fixo. `fallback` entra quando o valor falta. - **Quando:** sem `startAt`, começa ao disparar; com, fica agendada. Por padrão só envia de segunda a sexta, 9h às 18h, no fuso da empresa (`sendWindow`). ## 3. Conferir antes de enviar ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/message-preview -H "Authorization: Bearer $DONETALK_KEY" curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/review -H "Authorization: Bearer $DONETALK_KEY" ``` A prévia mostra o texto de cinco pessoas e as variáveis vazias. A revisão traz o custo estimado (até), o limite diário do número, os orçamentos e se vai precisar de aprovação. `POST /campaigns/{id}/test` manda a mensagem para o seu telefone. ## 4. Disparar ```bash curl -X POST https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/submit -H "Authorization: Bearer $DONETALK_KEY" ``` A resposta diz `running` (começou), `scheduled` (agendada) ou `pending_approval` (a regra da empresa pede aprovação, e alguém aprova no app). Uma chave marcada “Disparar campanhas sem esperar aprovação” não espera. Quem já recebeu marketing nos últimos 7 dias, pediu para sair ou está bloqueado fica de fora; a prévia do público diz quantos e por quê. ## 5. Acompanhar Pelos [avisos](/desenvolvedores/avisos/), sem consultar nada: `campaign.started`, `campaign.recipient.sent`, `.delivered`, `.read`, `.replied`, `.failed`, `.opted_out` e `campaign.completed`, com os totais. Quando o atendimento aberto pela campanha é concluído, chega `conversation.closed` com o desfecho e o `campaignId`. Ou consultando: ```bash curl "https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}" -H "Authorization: Bearer $DONETALK_KEY" curl "https://api.donetalk.com/v1/c/{empresa}/campaigns/{id}/recipients?status=replied" -H "Authorization: Bearer $DONETALK_KEY" ``` ## 6. Pausar, retomar, cancelar, reenviar `POST /campaigns/{id}/pause`, `/resume`, `/cancel`. As falhas que vale repetir voltam à fila com `POST /campaigns/{id}/retry` (todas, ou só alguns contatos ou códigos de erro). A campanha também pausa sozinha se o modelo for pausado pela Meta, a qualidade do número cair, muitos pedirem para sair ou o orçamento acabar. --- # Para IAs e agentes Esta documentação foi feita para ser lida e testada por uma IA, sem conta e sem risco. ## Onde ler - [llms.txt](/desenvolvedores/llms.txt): o índice, com um link para cada página em Markdown. - [llms-full.txt](/desenvolvedores/llms-full.txt): toda a documentação num arquivo só. - Cada página também existe em Markdown: troque a barra final do endereço por `.md` (ex.: `/desenvolvedores/campanhas.md`). - [OpenAPI](https://api.donetalk.com/v1/openapi.json?lang=pt): cada chamada, campo, escopo, erro e exemplo. `x-webhooks` traz os eventos; `x-errors`, os erros; `x-test-mode`, o modo teste. ## Testar de verdade, sem risco A empresa `demo` aceita a chave de teste pública `dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr`. Ela só simula: confere os pedidos com as regras reais e responde no formato real, com dados de exemplo, sem gravar nem enviar nada. ```bash export DONETALK_KEY=dt_test_demo_zRZ6twAhj4u9dZT0hEBrNFzr curl https://api.donetalk.com/v1/c/demo/me -H "Authorization: Bearer $DONETALK_KEY" ``` Para ver um erro, peça com `DoneTalk-Simulate: ` ([Modo teste](/desenvolvedores/modo-teste/)). ## Um pedido pronto para colar numa IA > Leia https://donetalk.com/desenvolvedores/llms-full.txt e, usando a empresa demo com a chave de teste pública, crie uma campanha para dois contatos com um cupom por pessoa, revise e dispare. Depois mostre como meu sistema saberia que um contato respondeu. ## Regras para agentes - Use uma chave de **Teste** enquanto desenvolve; produção só depois. - Mande `Idempotency-Key` em toda criação e envio. - Respeite `Retry-After` num `429`. - Nunca mande mensagens para números reais sem o consentimento do contato: marketing pede opt-in. --- # Conta ## Quem é a chave `GET /v1/c/{slug}/me` · Escopos: qualquer chave A empresa, o nome da chave, se é de produção ou teste, os escopos e o limite de chamadas. Bom primeiro teste de uma integração. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/me" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "memberId": "01a1b2c3-d4e5-7f60-8a9b-0c1d2e3f4a5b", "role": "integration", "permissions": [ "api.use", "campaigns.read", "campaigns.start", "campaigns.write", "contacts.read", "contacts.write" ], "company": { "slug": "captei", "name": "Captei" }, "key": { "name": "ERP Captei", "prefix": "dt_live_7Hq2mV0c", "environment": "live", "scopes": [ "campaigns:read", "campaigns:write", "campaigns:send", "contacts:write" ], "legacy": false, "skipApproval": false, "expiresAt": null }, "rateLimit": { "limit": 600, "windowSeconds": 60 } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Campanhas ## Listar campanhas `GET /v1/c/{slug}/campaigns` · Escopos: `campaigns:read` As campanhas mais novas primeiro, com os números de cada uma. Filtre por `status`. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `status` | string | não | até 40 caracteres | | `limit` | integer | não | até 200; mínimo 1; default `200` | | `cursor` | string | não | até 200 caracteres | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "campaigns": [ { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } ], "nextCursor": null } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Criar uma campanha `POST /v1/c/{slug}/campaigns` · Escopos: `campaigns:write` Cria um rascunho. Nada é enviado até `submit`. O público pode ser um segmento, um filtro ou uma lista de contatos: por id (`contactIds`) ou por telefone (`people`), com valores próprios de cada pessoa para as variáveis `value.`. Cada telefone vira um contato, criado ou atualizado, o que pede também o escopo contacts:write. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `name` | string | sim | até 120 caracteres | | `channelId` | string (uuid) | não | null | | `templateId` | string (uuid) | não | null | | `variables` | lista de objeto | não | até 40 | | `variables[].slot` | string | sim | | | `variables[].source` | um de `name`, `first_name`, `phone`, `fixed` · string | sim | | | `variables[].value` | string | não | até 500 caracteres | | `variables[].format` | um de `none`, `title`, `upper`, `lower`, `first` | não | default `"none"` | | `variables[].fallback` | string | não | até 200 caracteres; default `""` | | `buttons` | lista de objeto | não | até 10 | | `buttons[].index` | integer | sim | até 9 | | `buttons[].action` | um de `route`, `optout`, `none` | sim | | | `audience` | objeto | não | null | | `audience.kind` | um de `segment` | sim | | | `audience.segmentId` | string (uuid) | sim | | | `audience.conditions` | lista de objeto | sim | até 20 | | `audience.conditions[].field` | string | sim | até 80 caracteres | | `audience.conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `audience.conditions[].value` | string · number · boolean · um de `null` | não | | | `audience.contactIds` | lista de string (uuid) | não | até 20000; default `[]` | | `audience.people` | lista de objeto | não | até 20000 | | `audience.people[].phone` | string | sim | até 40 caracteres | | `audience.people[].name` | string | não | até 200 caracteres | | `audience.people[].fields` | object | não | | | `audience.people[].tags` | lista de string | não | até 20 | | `audience.people[].values` | object | não | | | `audience.values` | object | não | | | `excludeOpen` | boolean | não | | | `frequencyDays` | integer | não | até 90; null | | `startAt` | string (date-time) | não | null | | `sendWindow` | lista de objeto | não | até 14 | | `sendWindow[].day` | integer | sim | até 7; mínimo 1 | | `sendWindow[].from` | string | sim | | | `sendWindow[].to` | string | sim | | | `reply` | objeto | não | | | `reply.kind` | um de `team`, `flow`, `assistant` | não | default `"team"` | | `reply.id` | string (uuid) | não | default `null`; null | | `reply.goal` | string | não | até 200 caracteres; default `null`; null | | `successDays` | integer | não | até 60; mínimo 1 | | `stopRules` | objeto | não | | | `stopRules.templatePaused` | boolean | não | default `true` | | `stopRules.qualityLow` | boolean | não | default `true` | | `stopRules.optoutRate` | number | não | até 0.5; mínimo 0.005; default `0.03`; null | | `stopRules.budget` | boolean | não | default `true` | | `budgetMicros` | integer | não | até 1000000000000000; null | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Reativação · outubro", "channelId": "01a0cccc-0000-7000-8000-000000000002", "templateId": "01a0cad0-0000-7000-8000-000000000002", "variables": [ { "slot": "body.1", "source": "first_name", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "people": [ { "phone": "+5548999990001", "name": "Ana Souza", "values": { "cupom": "ana10" } }, { "phone": "+5548999990002", "name": "Bruno Lima", "values": { "cupom": "bru15" } } ] }, "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701" }, "startAt": "2026-10-24T12:00:00.000Z" }' ``` ### Resposta 201 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Erros possíveis - `400` `template_other_account` - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver uma campanha `GET /v1/c/{slug}/campaigns/{id}` · Escopos: `campaigns:read` A campanha com o funil: enviadas, entregues, lidas, respostas, falhas, sucessos e custo (em micros: 1.000.000 = 1 unidade da moeda). ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "running", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": "2026-10-24T12:00:00.000Z", "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Editar um rascunho `PATCH /v1/c/{slug}/campaigns/{id}` · Escopos: `campaigns:write` Só um rascunho muda. Mande apenas o que muda. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `name` | string | não | até 120 caracteres | | `channelId` | string (uuid) | não | null | | `templateId` | string (uuid) | não | null | | `variables` | lista de objeto | não | até 40 | | `variables[].slot` | string | sim | | | `variables[].source` | um de `name`, `first_name`, `phone`, `fixed` · string | sim | | | `variables[].value` | string | não | até 500 caracteres | | `variables[].format` | um de `none`, `title`, `upper`, `lower`, `first` | não | default `"none"` | | `variables[].fallback` | string | não | até 200 caracteres; default `""` | | `buttons` | lista de objeto | não | até 10 | | `buttons[].index` | integer | sim | até 9 | | `buttons[].action` | um de `route`, `optout`, `none` | sim | | | `audience` | objeto | não | null | | `audience.kind` | um de `segment` | sim | | | `audience.segmentId` | string (uuid) | sim | | | `audience.conditions` | lista de objeto | sim | até 20 | | `audience.conditions[].field` | string | sim | até 80 caracteres | | `audience.conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `audience.conditions[].value` | string · number · boolean · um de `null` | não | | | `audience.contactIds` | lista de string (uuid) | não | até 20000; default `[]` | | `audience.people` | lista de objeto | não | até 20000 | | `audience.people[].phone` | string | sim | até 40 caracteres | | `audience.people[].name` | string | não | até 200 caracteres | | `audience.people[].fields` | object | não | | | `audience.people[].tags` | lista de string | não | até 20 | | `audience.people[].values` | object | não | | | `audience.values` | object | não | | | `excludeOpen` | boolean | não | | | `frequencyDays` | integer | não | até 90; null | | `startAt` | string (date-time) | não | null | | `sendWindow` | lista de objeto | não | até 14 | | `sendWindow[].day` | integer | sim | até 7; mínimo 1 | | `sendWindow[].from` | string | sim | | | `sendWindow[].to` | string | sim | | | `reply` | objeto | não | | | `reply.kind` | um de `team`, `flow`, `assistant` | não | default `"team"` | | `reply.id` | string (uuid) | não | default `null`; null | | `reply.goal` | string | não | até 200 caracteres; default `null`; null | | `successDays` | integer | não | até 60; mínimo 1 | | `stopRules` | objeto | não | | | `stopRules.templatePaused` | boolean | não | default `true` | | `stopRules.qualityLow` | boolean | não | default `true` | | `stopRules.optoutRate` | number | não | até 0.5; mínimo 0.005; default `0.03`; null | | `stopRules.budget` | boolean | não | default `true` | | `budgetMicros` | integer | não | até 1000000000000000; null | ### Exemplo de pedido ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Reativação · outubro (2)", "frequencyDays": 7 }' ``` ### Resposta 200 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "name": "Reativação · outubro", "status": "draft", "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "template": { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "category": "marketing" }, "variables": [ { "slot": "body.1", "source": "first_name", "format": "none", "fallback": "tudo bem" }, { "slot": "body.2", "source": "value.cupom", "format": "upper", "fallback": "" } ], "buttons": [ { "index": 0, "action": "route" } ], "audience": { "kind": "contacts", "contactIds": [ "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "01a0d05a-3ee3-75bd-9db5-dc9856f079c9" ] }, "excludeOpen": true, "frequencyDays": 7, "startAt": "2026-10-24T12:00:00.000Z", "sendWindow": [ { "day": 1, "from": "09:00", "to": "18:00" } ], "reply": { "kind": "team", "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "goal": null }, "successDays": 7, "stopRules": { "templatePaused": true, "qualityLow": true, "optoutRate": 0.03, "budget": true }, "budgetMicros": null, "estimate": { "micros": 77824000, "currency": "BRL" }, "audienceCount": 1240, "header": null, "approval": { "required": false, "requestedTo": null, "requestedAt": null, "approvedBy": null, "approvedAt": null, "rejectedReason": null }, "createdBy": null, "createdByKind": "api", "startedAt": null, "paused": null, "completedAt": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z", "stats": { "audience": 1240, "queued": 0, "sending": 0, "sent": 1216, "delivered": 1198, "read": 874, "failed": 18, "skipped": 24, "replied": 141, "optedOut": 6, "successes": 37, "costMicros": 77824000, "followMicros": 1260000, "aiUsdMicros": 0 } } } ``` ### Erros possíveis - `400` `template_other_account` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `422` `validation_failed` - `429` `rate_limited` ## Apagar uma campanha `DELETE /v1/c/{slug}/campaigns/{id}` · Escopos: `campaigns:write` Rascunhos, canceladas e concluídas. Uma campanha enviando precisa ser cancelada antes. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/campaigns/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Duplicar `POST /v1/c/{slug}/campaigns/{id}/duplicate` · Escopos: `campaigns:write` Um rascunho novo com a mesma configuração e o mesmo público. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/duplicate" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 201 ```json { "campaign": { "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Pôr a imagem ou documento do cabeçalho `PUT /v1/c/{slug}/campaigns/{id}/header` · Escopos: `campaigns:write` Para modelos com cabeçalho de mídia: envie o arquivo em `POST /uploads` e passe o `uploadId`. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `uploadId` | string (uuid) | sim | | ### Exemplo de pedido ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/campaigns/:id/header" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "uploadId": "01a3d1e2-f3a4-7b5c-8d6e-7f8091a2b3c4" }' ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `422` `validation_failed` - `429` `rate_limited` ## Prévia do público `POST /v1/c/{slug}/campaigns/{id}/audience-preview` · Escopos: `campaigns:read` Quantos recebem e quantos ficam de fora, por motivo: bloqueado, sem WhatsApp, pediu para sair, repetido, frequência de marketing, conversa aberta. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/audience-preview" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "found": 1264, "excluded": { "blocked": 0, "no_whatsapp": 2, "opted_out": 18, "duplicate": 0, "frequency": 4, "open_conversation": 0 }, "openConversations": 3, "receive": 1240, "samples": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Prévia da mensagem `POST /v1/c/{slug}/campaigns/{id}/message-preview` · Escopos: `campaigns:read` Como a mensagem chega para cinco pessoas do público, e quais variáveis ficariam vazias. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/message-preview" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "slots": [ "body.1", "body.2" ], "quickReplies": [ { "index": 0, "text": "Quero o cupom" } ], "samples": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "missing": [] } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Revisar: custo, conferências e aprovação `POST /v1/c/{slug}/campaigns/{id}/review` · Escopos: `campaigns:read` O custo estimado (até), o limite diário do número, os orçamentos, quantas pessoas ficariam sem alguma variável e se a campanha precisará de aprovação. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/review" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "estimate": { "currency": "BRL", "people": 1240, "totalMicros": 77824000, "markets": [ { "market": "BR", "people": 1240, "rateMicros": 62760, "micros": 77822400 } ] }, "checks": { "templateApproved": true, "channelActive": true, "quality": "GREEN", "dailyLimit": 1000, "days": 2, "budgets": [], "campaignBudgetMicros": null, "missingVariables": 0 }, "approval": { "required": false, "approvers": [] } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Mandar um teste `POST /v1/c/{slug}/campaigns/{id}/test` · Escopos: `campaigns:write` Manda a mensagem para um telefone (o seu), sem contar nos números da campanha. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `phone` | string | sim | até 40 caracteres | | `name` | string | não | até 200 caracteres | | `values` | object | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/test" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5548999990009", "name": "Leo", "values": { "cupom": "teste10" } }' ``` ### Resposta 200 ```json { "ok": true, "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "messageId": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Disparar ou agendar `POST /v1/c/{slug}/campaigns/{id}/submit` · Escopos: `campaigns:send` Com `startAt` no futuro, fica agendada; sem, começa agora. Se a regra de aprovação da empresa pedir, a campanha fica `pending_approval` até alguém aprovar no app, a menos que a chave tenha “Disparar sem esperar aprovação”. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `approverId` | string (uuid) | não | default `null`; null | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/submit" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` ### Resposta 200 ```json { "status": "scheduled" } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `409` `campaign_not_editable` - `409` `template_not_approved` - `409` `campaign_audience_empty` - `422` `validation_failed` - `429` `rate_limited` ## Pausar `POST /v1/c/{slug}/campaigns/{id}/pause` · Escopos: `campaigns:send` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/pause" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "status": "paused" } ``` ### Erros possíveis - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Retomar `POST /v1/c/{slug}/campaigns/{id}/resume` · Escopos: `campaigns:send` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/resume" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "status": "running" } ``` ### Erros possíveis - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Cancelar `POST /v1/c/{slug}/campaigns/{id}/cancel` · Escopos: `campaigns:send` Para de enviar de vez. O que já saiu continua contando nos resultados. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/cancel" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "status": "cancelled" } ``` ### Erros possíveis - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Reenviar as falhas `POST /v1/c/{slug}/campaigns/{id}/retry` · Escopos: `campaigns:send` Volta para a fila quem falhou, todos ou só alguns contatos ou códigos de erro. Falhas que não adianta repetir (número sem WhatsApp, por exemplo) ficam de fora. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `contactIds` | lista de string (uuid) | não | até 20000 | | `errorCodes` | lista de string | não | até 50 | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/campaigns/:id/retry" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "errorCodes": [ "131049" ] }' ``` ### Resposta 200 ```json { "requeued": 12 } ``` ### Erros possíveis - `400` `campaign_wrong_status` - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Destinatários, um por um `GET /v1/c/{slug}/campaigns/{id}/recipients` · Escopos: `campaigns:read` Cada contato com o status da mensagem, a resposta, o botão tocado e o atendimento que ela abriu, com o desfecho. `status` filtra (`sent`, `delivered`, `read`, `failed`, `skipped`, `replied`, `success`); `format=csv` baixa tudo. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `status` | string | não | até 20 caracteres | | `limit` | integer | não | até 500; mínimo 1; default `100` | | `offset` | integer | não | default `0` | | `format` | um de `json`, `csv` | não | default `"json"` | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id/recipients" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "recipients": [ { "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "externalRef": "erp-88213", "address": "5548999990001", "status": "read", "skipReason": null, "errorCode": null, "sentAt": "2026-10-24T12:00:04.000Z", "deliveredAt": "2026-10-24T12:00:06.000Z", "readAt": "2026-10-24T12:03:51.000Z", "repliedAt": "2026-10-24T12:04:02.000Z", "buttonIndex": 0, "optedOutAt": null, "successAt": null, "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "nextAttemptAt": null, "conversation": { "status": "closed", "handler": "human", "lastInboundAt": "2026-10-24T12:09:10.000Z", "lastMessageAt": "2026-10-24T12:20:41.000Z", "lastMessageBy": "member", "closedAt": "2026-10-24T12:20:41.000Z", "closedBy": "member", "outcome": { "code": "converted", "category": "success", "label": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "note": "Fechou o plano anual com o cupom ANA10." } }, "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" } } ] } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Falhas, botões e cliques `GET /v1/c/{slug}/campaigns/{id}/insights` · Escopos: `campaigns:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/campaigns/:id/insights" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "failures": [ { "code": "131026", "count": 9, "waiting": 0 } ], "skipped": [ { "reason": "opted_out", "count": 18 } ], "buttons": [ { "index": 0, "text": "Quero o cupom", "taps": 96 } ], "links": [], "perHour": [ { "hour": "2026-10-24T12:00:00.000Z", "count": 640 } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `campaign_not_found` - `422` `validation_failed` - `429` `rate_limited` --- # Segmentos ## Listar segmentos `GET /v1/c/{slug}/segments` · Escopos: `contacts:read` · `campaigns:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/segments" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "segments": [ { "id": "01a1a0b0-1c2d-7e3f-8a9b-0c1d2e3f4a5b", "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ], "count": 312, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Criar um segmento `POST /v1/c/{slug}/segments` · Escopos: `contacts:write` Um grupo de contatos por condições: etiqueta, origem, último desfecho, dias desde a última conversa ou o cadastro, consentimento de marketing, nome, WhatsApp e qualquer campo (`field.`). ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `name` | string | sim | até 120 caracteres | | `conditions` | lista de objeto | sim | até 20 | | `conditions[].field` | string | sim | até 80 caracteres | | `conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `conditions[].value` | string · number · boolean · um de `null` | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/segments" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ] }' ``` ### Resposta 201 ```json { "segment": { "id": "01a1a0b0-1c2d-7e3f-8a9b-0c1d2e3f4a5b" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar um segmento `PUT /v1/c/{slug}/segments/{id}` · Escopos: `contacts:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `name` | string | sim | até 120 caracteres | | `conditions` | lista de objeto | sim | até 20 | | `conditions[].field` | string | sim | até 80 caracteres | | `conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `conditions[].value` | string · number · boolean · um de `null` | não | | ### Exemplo de pedido ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/segments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Clientes do plano anual", "conditions": [ { "field": "field.plano", "op": "eq", "value": "anual" } ] }' ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Apagar um segmento `DELETE /v1/c/{slug}/segments/{id}` · Escopos: `contacts:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/segments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Contar quem entra `POST /v1/c/{slug}/segments/count` · Escopos: `contacts:read` · `campaigns:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `conditions` | lista de objeto | sim | até 20 | | `conditions[].field` | string | sim | até 80 caracteres | | `conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `conditions[].value` | string · number · boolean · um de `null` | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/segments/count" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ { "field": "tag", "op": "has", "value": "01a12150-3610-7c00-b680-188c2b4c7313" } ] }' ``` ### Resposta 200 ```json { "count": 312 } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Buscar contatos por condições `POST /v1/c/{slug}/contacts/search` · Escopos: `contacts:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `segmentId` | string (uuid) | não | | | `conditions` | lista de objeto | não | até 20; default `[]` | | `conditions[].field` | string | sim | até 80 caracteres | | `conditions[].op` | um de `eq`, `neq`, `has`, `not_has`, `contains`, `empty`, `not_empty`, `gt`, `lt`, `none` | sim | | | `conditions[].value` | string · number · boolean · um de `null` | não | | | `q` | string | não | até 100 caracteres | | `limit` | integer | não | até 200; mínimo 1; default `50` | | `offset` | integer | não | até 1000000; default `0` | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/search" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "conditions": [ { "field": "marketing", "op": "eq", "value": "opted_in" } ], "limit": 50 }' ``` ### Resposta 200 ```json { "total": 312, "marketingAllowed": 298, "contacts": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "source": "api", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "address": "5548999990001", "marketing": "opted_in", "lastOutcome": "converted", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Contatos ## Listar contatos `GET /v1/c/{slug}/contacts` · Escopos: `contacts:read` Os mais ativos primeiro. `q` busca por nome ou telefone; `tag` filtra por etiqueta; `before` (o `lastActivityAt` do último da página) traz a próxima página. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `q` | string | não | até 200 caracteres | | `limit` | integer | não | até 100; mínimo 1; default `50` | | `before` | string (date-time) | não | | | `tag` | string (uuid) | não | | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "contacts": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001", "channelKind": "whatsapp", "source": "api", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ] } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Criar um contato `POST /v1/c/{slug}/contacts` · Escopos: `contacts:write` Para criar ou atualizar vários de uma vez (ou um que talvez já exista), use `POST /contacts/import`. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `displayName` | string | sim | até 200 caracteres | | `phone` | string | sim | | | `locale` | um de `pt-BR`, `es`, `en` | não | | | `fields` | object | não | | | `externalRef` | string | não | até 200 caracteres | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "displayName": "Ana Souza", "phone": "+5548999990001", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25" } }' ``` ### Resposta 201 ```json { "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `409` `contact_exists` - `422` `validation_failed` - `429` `rate_limited` ## Criar ou atualizar contatos (até 1.000) `POST /v1/c/{slug}/contacts/import` · Escopos: `contacts:write` Pelo telefone: quem já existe é atualizado (nome, campos, etiquetas), quem não existe é criado. Cada linha volta com o id do contato. Uma linha com problema não derruba as outras. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `rows` | lista de objeto | sim | até 1000 | | `rows[].phone` | string | sim | até 40 caracteres | | `rows[].name` | string | não | até 200 caracteres | | `rows[].fields` | object | não | | | `rows[].tags` | lista de string | não | até 20 | | `rows[].externalRef` | string | não | até 200 caracteres | | `rows[].marketingOptIn` | boolean | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/import" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "rows": [ { "phone": "+5548999990001", "name": "Ana Souza", "tags": [ "VIP" ], "externalRef": "erp-88213" }, { "phone": "48 99999-0002", "name": "Bruno Lima", "fields": { "plano": "mensal" }, "marketingOptIn": true } ] }' ``` ### Resposta 200 ```json { "created": 1, "updated": 1, "errors": [ { "row": 2, "reason": "invalid_phone" } ], "contacts": [ { "row": 0, "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "created": false }, { "row": 1, "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "created": true } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver um contato `GET /v1/c/{slug}/contacts/{id}` · Escopos: `contacts:read` O contato com seus campos, números, consentimentos, últimos atendimentos e etiquetas, e as definições dos campos da empresa. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "displayName": "Ana Souza", "address": "5548999990001", "channelKind": "whatsapp", "source": "api", "externalRef": "erp-88213", "fields": { "cpf": "529.982.247-25", "plano": "anual" }, "isBlocked": false, "lastActivityAt": "2026-10-22T18:40:02.000Z", "createdAt": "2026-09-23T22:19:30.396Z", "firstName": "Ana", "lastName": "Souza", "locale": "pt-BR", "timezone": null, "blockedReason": null }, "identities": [ { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "channel_kind": "whatsapp", "address": "5548999990001", "external_id": null, "provider_display_name": "Ana", "is_primary": true, "last_seen_at": "2026-10-22T18:40:02.000Z" } ], "consents": [ { "purpose": "marketing", "channel_kind": "whatsapp", "status": "opted_in", "source": "api", "occurred_at": "2026-10-01T10:00:00.000Z" } ], "conversations": [ { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "closed", "source_kind": "campaign", "imported_from": null, "created_at": "2026-10-24T12:00:04.000Z", "closed_at": "2026-10-24T12:20:41.000Z", "channel_id": "01a0cccc-0000-7000-8000-000000000002", "outcome_code": "converted", "is_success": true } ], "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "fieldDefinitions": [ { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "ai_extractable": true, "required": false, "sort": 1 } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Editar um contato `PATCH /v1/c/{slug}/contacts/{id}` · Escopos: `contacts:write` `fields` junta com os campos que o contato já tem; mande `null` num campo para apagá-lo. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `displayName` | string | não | até 200 caracteres | | `firstName` | string | não | até 100 caracteres; null | | `lastName` | string | não | até 100 caracteres; null | | `locale` | um de `pt-BR`, `es`, `en` | não | null | | `externalRef` | string | não | até 200 caracteres; null | | `fields` | object | não | | | `isBlocked` | boolean | não | | | `blockedReason` | string | não | até 200 caracteres; null | ### Exemplo de pedido ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/contacts/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "fields": { "plano": "anual" }, "externalRef": "erp-88213" }' ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Registrar consentimento `POST /v1/c/{slug}/contacts/{id}/consents` · Escopos: `contacts:write` Opt-in ou opt-out por finalidade (atendimento, utilidade, marketing). Marketing com opt-out tira o contato das campanhas de marketing. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `purpose` | um de `service`, `utility`, `marketing` | sim | | | `status` | um de `opted_in`, `opted_out` | sim | | | `source` | um de `form`, `import`, `api`, `message`, `keyword` | não | default `"form"` | | `evidence` | object | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/consents" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "purpose": "marketing", "status": "opted_in", "source": "api" }' ``` ### Resposta 201 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` ## Pôr uma etiqueta `PUT /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Escopos: `contacts:write` Pode iniciar os fluxos que começam quando essa etiqueta é colocada. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | | `tagId` | O id da etiqueta. | ### Exemplo de pedido ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Tirar uma etiqueta `DELETE /v1/c/{slug}/contacts/{id}/tags/{tagId}` · Escopos: `contacts:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | | `tagId` | O id da etiqueta. | ### Exemplo de pedido ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/tags/:tagId" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Fichas de contexto `GET /v1/c/{slug}/contacts/{id}/context-cards` · Escopos: `contacts:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "cards": [ { "key": "erp", "source": "ERP Captei", "title": "Cliente desde 2023", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" }, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mostrar uma ficha a quem atende `PUT /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Escopos: `contacts:write` Uma ficha do seu sistema que aparece ao lado da conversa (plano, pedidos, saldo). A mesma `key` substitui a anterior. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | | `key` | A chave (do campo ou da ficha). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `title` | string | sim | até 120 caracteres | | `source` | string | não | até 60 caracteres | | `status` | string | não | até 60 caracteres; null | | `tone` | um de `neutral`, `success`, `warning`, `danger`, `info` | não | default `"neutral"` | | `fields` | lista de objeto | não | até 12; default `[]` | | `fields[].label` | string | sim | até 60 caracteres | | `fields[].value` | string | sim | até 300 caracteres | | `link` | objeto | não | null | | `link.url` | string (uri) | sim | até 2000 caracteres | | `link.label` | string | não | até 60 caracteres | ### Exemplo de pedido ```bash curl -X PUT "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Cliente desde 2023", "source": "ERP Captei", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" } }' ``` ### Resposta 200 ```json { "card": { "key": "erp", "source": "ERP Captei", "title": "Cliente desde 2023", "status": "Plano anual", "tone": "success", "fields": [ { "label": "Pedidos", "value": "14" } ], "link": { "url": "https://erp.captei.com.br/clientes/88213", "label": "Abrir no ERP" }, "updatedAt": "2026-10-23T13:02:11.000Z" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Tirar uma ficha `DELETE /v1/c/{slug}/contacts/{id}/context-cards/{key}` · Escopos: `contacts:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | | `key` | A chave (do campo ou da ficha). | ### Exemplo de pedido ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/contacts/:id/context-cards/:key" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Apagar os dados do contato (LGPD) `POST /v1/c/{slug}/contacts/{id}/erase` · Escopos: `contacts:delete` A pedido do titular: o contato e suas mensagens são anonimizados de vez. Não tem volta. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contacts/:id/erase" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `422` `validation_failed` - `429` `rate_limited` --- # Campos dos contatos ## Listar os campos dos contatos `GET /v1/c/{slug}/contact-fields` · Escopos: `fields:read` · `contacts:read` Os campos da empresa (chave, nome nos três idiomas, tipo, opções). Os valores de cada contato vêm em `fields` do contato. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/contact-fields" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "fields": [ { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "aiExtractable": true, "aiExtractionHint": null, "required": false, "sort": 1, "isActive": true } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Criar um campo `POST /v1/c/{slug}/contact-fields` · Escopos: `fields:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `key` | string | sim | | | `label` | string · object | sim | | | `type` | um de `text`, `number`, `date`, `boolean`, `select`, `phone`, `email`, `cpf`, `cnpj` | sim | | | `options` | lista de string | não | até 50; null | | `aiExtractable` | boolean | não | default `false` | | `aiExtractionHint` | string | não | até 300 caracteres; null | | `required` | boolean | não | default `false` | | `sort` | integer | não | até 1000 | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/contact-fields" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "key": "plano", "label": "Plano", "type": "select", "options": [ "mensal", "anual" ] }' ``` ### Resposta 201 ```json { "field": { "key": "cpf", "label": { "pt-BR": "CPF", "en": "CPF", "es": "CPF" }, "type": "cpf", "options": null, "aiExtractable": true, "aiExtractionHint": null, "required": false, "sort": 1, "isActive": true } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar um campo `PATCH /v1/c/{slug}/contact-fields/{key}` · Escopos: `fields:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `key` | A chave (do campo ou da ficha). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `label` | string · object | não | | | `options` | lista de string | não | até 50; null | | `aiExtractable` | boolean | não | | | `aiExtractionHint` | string | não | até 300 caracteres; null | | `required` | boolean | não | | | `sort` | integer | não | até 1000 | | `isActive` | boolean | não | | ### Exemplo de pedido ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/contact-fields/:key" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "options": [ "mensal", "semestral", "anual" ] }' ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Modelos ## Listar modelos `GET /v1/c/{slug}/templates` · Escopos: `templates:read` · `campaigns:write` · `messages:send_template` Os modelos de mensagem de cada conta do WhatsApp, com status na Meta, categoria e componentes (as variáveis `{{1}}` ficam no texto). ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/templates" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "templates": [ { "id": "01a0cad0-0000-7000-8000-000000000002", "name": "reativacao_cupom", "language": "pt_BR", "category": "marketing", "status": "approved", "quality": "GREEN", "accountId": "01a0cccc-0000-7000-8000-000000000001", "accountName": "Captei WABA", "components": [ { "type": "BODY", "text": "Oi {{1}}! Seu cupom {{2}} vale até sexta. Quer usar agora?" }, { "type": "BUTTONS", "buttons": [ { "type": "QUICK_REPLY", "text": "Quero o cupom" } ] } ], "rejectionReason": null, "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Mensagens ## Mandar um modelo para um telefone `POST /v1/c/{slug}/messages/template` · Escopos: `messages:send_template` Na conversa aberta do contato, ou numa nova, atendida como o número atende o que chega. O contato é criado se não existir. `idempotencyKey` (ou o cabeçalho Idempotency-Key) evita mandar duas vezes. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `phone` | string | sim | | | `contactName` | string | não | até 200 caracteres | | `channelId` | string (uuid) | não | | | `templateId` | string (uuid) | sim | | | `body` | lista de string | não | até 20; default `[]` | | `header` | lista de string | não | até 5; default `[]` | | `buttons` | object | não | default `{}` | | `handling` | um de `number`, `team` | não | default `"number"` | | `assigneeEmail` | string (email) | não | até 320 caracteres | | `idempotencyKey` | string | sim | até 200 caracteres | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/messages/template" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+5548999990001", "contactName": "Ana Souza", "templateId": "01a0cad0-0000-7000-8000-000000000002", "body": [ "Ana", "ANA10" ], "idempotencyKey": "pedido-88213-lembrete" }' ``` ### Resposta 201 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "status": "queued" }, "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" }, "replay": false } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Status de uma mensagem e a resposta `GET /v1/c/{slug}/messages/{id}` · Escopos: `conversations:read` · `messages:send_template` · `messages:send_text` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/messages/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "direction": "outbound", "from": null, "type": "template", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "errorCode": null, "createdAt": "2026-10-23T13:02:11.000Z", "sentAt": "2026-10-23T13:02:12.000Z", "deliveredAt": "2026-10-23T13:02:13.000Z", "readAt": "2026-10-23T13:05:40.000Z", "reply": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c9", "type": "button", "text": "Quero o cupom", "at": "2026-10-23T13:05:52.000Z" } } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mensagens de um telefone `GET /v1/c/{slug}/messages` · Escopos: `conversations:read` As mensagens de um telefone desde um momento, mais novas primeiro (com ou sem o nono dígito). ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `phone` | string | sim | | | `since` | string (date-time) | sim | | | `channelId` | string (uuid) | não | | | `direction` | um de `inbound`, `outbound` | não | | | `limit` | integer | não | até 100; mínimo 1; default `20` | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/messages" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "messages": [ { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "direction": "outbound", "from": null, "type": "template", "text": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "errorCode": null, "createdAt": "2026-10-23T13:02:11.000Z", "sentAt": "2026-10-23T13:02:12.000Z", "deliveredAt": "2026-10-23T13:02:13.000Z", "readAt": "2026-10-23T13:05:40.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Atendimentos ## Listar atendimentos `GET /v1/c/{slug}/conversations` · Escopos: `conversations:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `view` | um de `mine`, `team`, `queue`, `waiting_contact`, `snoozed`, `closed`, `mentions`, `all` | não | default `"mine"` | | `limit` | integer | não | até 100; mínimo 1; default `50` | | `before` | string (date-time) | não | | | `q` | string | não | até 200 caracteres | | `tag` | string (uuid) | não | | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/conversations" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "conversations": [ { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "active", "handler": "human", "priority": "normal", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "unreadCount": 1, "lastMessageAt": "2026-10-23T13:05:52.000Z", "lastInboundAt": "2026-10-23T13:05:52.000Z", "sessionWindowEndsAt": "2026-10-24T13:05:52.000Z", "snoozedUntil": null, "sourceKind": "campaign", "createdAt": "2026-10-23T13:02:11.000Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" }, "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "lastMessage": { "body": "Quero o cupom", "direction": "inbound", "type": "button", "status": "received" } } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Abrir um atendimento por modelo `POST /v1/c/{slug}/conversations` · Escopos: `messages:send_template` Para um contato já cadastrado. `assigneeMemberId` escolhe quem atende; sem ele, o atendimento espera a resposta e entra na fila da equipe. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `contactId` | string (uuid) | sim | | | `channelId` | string (uuid) | não | | | `templateId` | string (uuid) | sim | | | `parameters` | object | não | default `{}` | | `headerUploadId` | string (uuid) | não | | | `headerLink` | string (uri) | não | até 2000 caracteres | | `teamId` | string (uuid) | não | null | | `goal` | string | não | até 60 caracteres | | `assigneeMemberId` | string (uuid) | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "templateId": "01a0cad0-0000-7000-8000-000000000002", "parameters": { "1": "Ana" } }' ``` ### Resposta 201 ```json { "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677" }, "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `404` `contact_not_found` - `409` `template_not_approved` - `422` `validation_failed` - `429` `rate_limited` ## Ver um atendimento `GET /v1/c/{slug}/conversations/{id}` · Escopos: `conversations:read` O atendimento com as mensagens, os eventos (atribuições, transferências) e, quando concluído, o desfecho. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/conversations/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "conversation": { "id": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "status": "active", "handler": "human", "priority": "normal", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "assigneeId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "unreadCount": 1, "lastMessageAt": "2026-10-23T13:05:52.000Z", "lastInboundAt": "2026-10-23T13:05:52.000Z", "sessionWindowEndsAt": "2026-10-24T13:05:52.000Z", "snoozedUntil": null, "sourceKind": "campaign", "createdAt": "2026-10-23T13:02:11.000Z", "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e" } ], "contact": { "id": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "name": "Ana Souza", "address": "5548999990001" }, "channel": { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei" }, "lastMessage": { "body": "Quero o cupom", "direction": "inbound", "type": "button", "status": "received" }, "goal": null, "outcome": null, "closedAt": null }, "messages": [ { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "direction": "outbound", "author": { "kind": "campaign", "id": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b" }, "type": "template", "body": "Oi Ana! Seu cupom ANA10 vale até sexta. Quer usar agora?", "status": "read", "error": null, "campaignId": "01a2b3c4-5d6e-7f80-9a1b-2c3d4e5f6a7b", "createdAt": "2026-10-23T13:02:11.000Z" } ], "pinned": [], "events": [] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mandar uma mensagem no atendimento `POST /v1/c/{slug}/conversations/{id}/messages` · Escopos: `messages:send_template` · `messages:send_text` `type: template` com o escopo messages:send_template. `text` e `media` (arquivo de `POST /uploads`) pedem messages:send_text e a janela de 24 horas aberta. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `type` | um de `text` | sim | | | `text` | string | sim | até 4096 caracteres | | `replyToProviderMessageId` | string | não | | | `linkPreview` | boolean | não | | | `gateDecisionId` | string (uuid) | não | | | `gateAction` | um de `accepted`, `edited`, `overridden` | não | | | `templateId` | string (uuid) | sim | | | `parameters` | object | não | default `{}` | | `headerUploadId` | string (uuid) | não | | | `headerLink` | string (uri) | não | até 2000 caracteres | | `uploadId` | string (uuid) | sim | | | `caption` | string | não | até 1024 caracteres | | `contactIds` | lista de string (uuid) | sim | até 10 | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/messages" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "text", "text": "Oi Ana! Seu pedido saiu para entrega." }' ``` ### Resposta 202 ```json { "message": { "id": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "status": "queued", "createdAt": "2026-10-23T13:02:11.000Z", "media": null } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `403` `integration_template_only` - `409` `window_closed` - `422` `validation_failed` - `429` `rate_limited` ## Concluir com um desfecho `POST /v1/c/{slug}/conversations/{id}/close` · Escopos: `conversations:write` `outcomeCode` vem de `GET /outcomes`. Com `ifNoReplyHours`, conclui só se o contato não responder nesse prazo. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `outcomeCode` | string | sim | até 60 caracteres | | `note` | string | não | até 4000 caracteres | | `ifNoReplyHours` | integer | não | até 720; mínimo 1 | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/close" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "outcomeCode": "converted", "note": "Fechou o plano anual." }' ``` ### Resposta 200 ```json { "ok": true, "isSuccess": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Reabrir `POST /v1/c/{slug}/conversations/{id}/reopen` · Escopos: `conversations:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/conversations/:id/reopen" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Enviar um arquivo `POST /v1/c/{slug}/uploads` · Escopos: `messages:send_text` · `campaigns:write` · `messages:send_template` multipart/form-data com o campo `file` (e `intent`: media, document, audio, sticker). Devolve o `id` para mandar numa mensagem ou pôr no cabeçalho de uma campanha. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido `multipart/form-data`: `file` + `intent` (media, document, audio, sticker). ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/uploads" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 201 ```json { "upload": { "id": "01a3d1e2-f3a4-7b5c-8d6e-7f8091a2b3c4", "mime": "image/jpeg", "sizeBytes": 182340, "filename": "cupom.jpg", "kind": "image", "voice": false, "conversion": null, "durationMs": null, "width": 1080, "height": 1080 } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Números, equipes e etiquetas ## Números de WhatsApp `GET /v1/c/{slug}/channels` · Escopos: `workspace:read` · `campaigns:write` · `messages:send_template` · `templates:read` Os números da empresa, com a qualidade e o limite diário que a Meta deu a cada um. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/channels" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "channels": [ { "id": "01a0cccc-0000-7000-8000-000000000002", "name": "Captei", "phone": "554896429898", "status": "active", "quality": "GREEN", "messagingTier": "TIER_1K", "account": { "id": "01a0cccc-0000-7000-8000-000000000001", "name": "Captei WABA" }, "currency": "BRL", "handling": { "mode": "flow", "teamId": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "flowId": "01a0d60a-3fc1-7df5-a07c-9769fd5701e6", "assistantId": null }, "createdAt": "2026-09-22T20:14:21.670Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Equipes `GET /v1/c/{slug}/teams` · Escopos: `workspace:read` · `campaigns:write` Para mandar as respostas de uma campanha à equipe certa (`reply.id`). ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/teams" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "teams": [ { "id": "01a0cb22-89c0-7e02-b96b-3f4731dde701", "name": "Vendas", "description": null, "isActive": true, "distributionMode": "least_busy", "businessHoursId": null, "members": [ { "id": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "name": "Tayomara Batista", "presence": "online" } ] } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Etiquetas `GET /v1/c/{slug}/tags` · Escopos: `workspace:read` · `contacts:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/tags" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "tags": [ { "id": "01a12150-3610-7c00-b680-188c2b4c7313", "name": { "pt-BR": "VIP", "en": "VIP", "es": "VIP" }, "color": "#92400e", "appliesTo": "both", "isActive": true, "contacts": 128, "conversations": 40 } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Desfechos `GET /v1/c/{slug}/outcomes` · Escopos: `workspace:read` · `conversations:read` · `conversations:write` Como um atendimento pode ser concluído (venda, sem interesse, resolvido…), com o código usado em `close` e nos avisos. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/outcomes" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "outcomes": [ { "id": "01a0cb22-0000-7000-8000-00000000000a", "code": "converted", "label": { "pt-BR": "Venda", "en": "Sale", "es": "Venta" }, "category": "success", "is_success": true, "requires_note": false, "reopen_allowed": true, "sort": 1 } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Agenda ## Tipos de agendamento `GET /v1/c/{slug}/appointment-types` · Escopos: `appointments:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointment-types" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "types": [ { "id": "01a1228c-c58f-796a-b3aa-54a953711c71", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "name": "Visita ao imóvel", "durationMin": 60, "agendaName": "Visitas aos imóveis", "timezone": "America/Sao_Paulo", "isActive": true } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Horários livres `GET /v1/c/{slug}/appointment-types/{id}/slots` · Escopos: `appointments:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `from` | string (date-time) | não | | | `to` | string (date-time) | não | | | `limit` | integer | não | até 500; mínimo 1; default `100` | | `contactId` | string (uuid) | não | | | `memberId` | string (uuid) | não | | | `exclude` | string (uuid) | não | | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointment-types/:id/slots" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "timezone": "America/Sao_Paulo", "durationMin": 60, "slots": [ { "start": "2026-10-27T13:00:00.000Z", "end": "2026-10-27T14:00:00.000Z", "memberIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ] } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Agendamentos `GET /v1/c/{slug}/appointments` · Escopos: `appointments:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Parâmetros de consulta | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `from` | string (date-time) | não | | | `to` | string (date-time) | não | | | `agendaId` | string (uuid) | não | | | `memberId` | string (uuid) | não | | | `mine` | integer | não | até 1; default `0` | | `status` | string | não | | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointments" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "appointments": [ { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Marcar `POST /v1/c/{slug}/appointments` · Escopos: `appointments:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `typeId` | string (uuid) | sim | | | `contactId` | string (uuid) | sim | | | `startsAt` | string (date-time) | sim | | | `conversationId` | string (uuid) | não | null | | `memberId` | string (uuid) | não | null | | `answers` | object | não | | | `notes` | string | não | até 2000 caracteres; null | | `force` | boolean | não | | | `confirm` | boolean | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "startsAt": "2026-10-27T13:00:00.000Z", "answers": { "imovel": "AP-2231" } }' ``` ### Resposta 201 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Ver um agendamento `GET /v1/c/{slug}/appointments/{id}` · Escopos: `appointments:read` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/appointments/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" }, "notices": [], "events": [], "history": [] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Remarcar `POST /v1/c/{slug}/appointments/{id}/reschedule` · Escopos: `appointments:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `startsAt` | string (date-time) | sim | | | `memberId` | string (uuid) | não | null | | `force` | boolean | não | | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments/:id/reschedule" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "startsAt": "2026-10-28T13:00:00.000Z" }' ``` ### Resposta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "booked", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Cancelar `POST /v1/c/{slug}/appointments/{id}/cancel` · Escopos: `appointments:write` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `reason` | string | não | até 300 caracteres; null | | `notify` | boolean | não | default `true` | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/appointments/:id/cancel" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "reason": "Cliente pediu" }' ``` ### Resposta 200 ```json { "appointment": { "id": "01a2f00d-1234-7abc-8def-0123456789ab", "agendaId": "01a1228c-c584-73f7-b7e7-bfaa0d02fed0", "agendaName": "Visitas aos imóveis", "typeId": "01a1228c-c58f-796a-b3aa-54a953711c71", "typeName": "Visita ao imóvel", "typeColor": "#1daa61", "contactId": "01a0d05a-3ee3-75bd-9db5-dc9856f079c8", "contactName": "Ana Souza", "conversationId": "01a3c0de-7a11-7b22-8c33-9d44e55f6677", "channelId": "01a0cccc-0000-7000-8000-000000000002", "memberId": "01a0cac1-4a6f-7646-b5f8-c1d19090016a", "memberName": "Tayomara Batista", "holderIds": [ "01a0cac1-4a6f-7646-b5f8-c1d19090016a" ], "status": "cancelled", "startsAt": "2026-10-27T13:00:00.000Z", "endsAt": "2026-10-27T14:00:00.000Z", "timezone": "America/Sao_Paulo", "location": "Rua Bahia, 120 – Higienópolis, São Paulo", "locationKind": "address", "onlineUrl": null, "answers": { "imovel": "AP-2231" }, "notes": null, "source": "api", "createdByKind": "api_key", "createdById": null, "confirmedAt": null, "cancelledAt": null, "cancelledByKind": null, "cancelReason": null, "rescheduleCount": 0, "previousStartsAt": null, "publicToken": "r3WqZ8", "createdAt": "2026-10-23T13:02:11.000Z" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` --- # Avisos (webhooks) ## Listar avisos `GET /v1/c/{slug}/webhooks` · Escopos: `webhooks:manage` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/webhooks" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "webhooks": [ { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Criar um aviso `POST /v1/c/{slug}/webhooks` · Escopos: `webhooks:manage` Um endereço do seu sistema e os eventos que ele recebe. O `secret` volta uma vez só: guarde para conferir as assinaturas. ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `url` | string (uri) | sim | até 2000 caracteres | | `events` | lista de um de `conversation.opened`, `conversation.closed`, `conversation.assigned`, `conversation.transferred`, `conversation.reopened`, `contact.updated`, `contact.consent_changed`, `message.received`, `message.sent`, `message.delivered`, `message.read`, `message.failed`, `flow.event`, `appointment.booked`, `appointment.rescheduled`, `appointment.cancelled`, `appointment.confirmed`, `appointment.attended`, `appointment.no_show`, `campaign.started`, `campaign.paused`, `campaign.resumed`, `campaign.completed`, `campaign.cancelled`, `campaign.recipient.sent`, `campaign.recipient.delivered`, `campaign.recipient.read`, `campaign.recipient.replied`, `campaign.recipient.failed`, `campaign.recipient.opted_out` | sim | até 30 | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/webhooks" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ] }' ``` ### Resposta 201 ```json { "webhook": { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" }, "secret": "dsf_whsec_4Jx…" } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Editar um aviso `PATCH /v1/c/{slug}/webhooks/{id}` · Escopos: `webhooks:manage` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Corpo do pedido | Campo | Tipo | Obrigatório | Detalhes | |---|---|---|---| | `url` | string (uri) | não | até 2000 caracteres | | `events` | lista de um de `conversation.opened`, `conversation.closed`, `conversation.assigned`, `conversation.transferred`, `conversation.reopened`, `contact.updated`, `contact.consent_changed`, `message.received`, `message.sent`, `message.delivered`, `message.read`, `message.failed`, `flow.event`, `appointment.booked`, `appointment.rescheduled`, `appointment.cancelled`, `appointment.confirmed`, `appointment.attended`, `appointment.no_show`, `campaign.started`, `campaign.paused`, `campaign.resumed`, `campaign.completed`, `campaign.cancelled`, `campaign.recipient.sent`, `campaign.recipient.delivered`, `campaign.recipient.read`, `campaign.recipient.replied`, `campaign.recipient.failed`, `campaign.recipient.opted_out` | não | até 30 | | `status` | um de `active`, `paused` | não | | ### Exemplo de pedido ```bash curl -X PATCH "https://api.donetalk.com/v1/c/demo/webhooks/:id" \ -H "Authorization: Bearer $DONETALK_KEY" \ -H "Content-Type: application/json" \ -d '{ "status": "paused" }' ``` ### Resposta 200 ```json { "webhook": { "id": "01a0cb03-417a-7da4-9ae2-70bc321eeef5", "url": "https://erp.captei.com.br/donetalk/avisos", "events": [ "campaign.completed", "campaign.recipient.replied", "conversation.closed" ], "status": "active", "failureCount": 0, "createdBy": null, "createdAt": "2026-10-23T13:02:11.000Z", "updatedAt": "2026-10-23T13:02:11.000Z" } } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Apagar um aviso `DELETE /v1/c/{slug}/webhooks/{id}` · Escopos: `webhooks:manage` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X DELETE "https://api.donetalk.com/v1/c/demo/webhooks/:id" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "ok": true } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Mandar um aviso de teste `POST /v1/c/{slug}/webhooks/{id}/test` · Escopos: `webhooks:manage` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X POST "https://api.donetalk.com/v1/c/demo/webhooks/:id/test" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 202 ```json { "deliveryId": "01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f", "eventId": "01a3c0de-8b22-7c33-9d44-0e55f6677889" } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited` ## Entregas recentes `GET /v1/c/{slug}/webhooks/{id}/deliveries` · Escopos: `webhooks:manage` ### Parâmetros do endereço | Campo | Detalhes | |---|---| | `slug` | O identificador da empresa no DoneTalk (o mesmo da chave). | | `id` | O id do registro. | ### Exemplo de pedido ```bash curl -X GET "https://api.donetalk.com/v1/c/demo/webhooks/:id/deliveries" \ -H "Authorization: Bearer $DONETALK_KEY" ``` ### Resposta 200 ```json { "deliveries": [ { "id": "01a3e4f5-a6b7-7c8d-9e0f-1a2b3c4d5e6f", "eventId": "01a3c0de-8b22-7c33-9d44-0e55f6677889", "eventType": "campaign.recipient.replied", "attempt": 1, "status": "delivered", "responseCode": 200, "responseMs": 84, "nextAttemptAt": null, "createdAt": "2026-10-24T12:04:03.000Z" } ] } ``` ### Erros possíveis - `401` `unauthorized` - `403` `insufficient_scope` - `422` `validation_failed` - `429` `rate_limited`