# Resultados de campanhas

Acompanhe os disparos feitos no painel e consulte a entrega de cada mensagem, sem enviar outra campanha.

A chave Bearer permite consultar somente as campanhas da sua empresa. Esta consulta lê os registros locais, atualizados pelos envios e pelos webhooks da Meta. Ela não consulta a Meta em tempo real.

## Encontrar a campanha

### GET /public/v1/campaigns

cURL · listar campanhas

```bash
curl "https://api.patrociniotech.com/public/v1/campaigns?limit=20" \
  -H "Authorization: Bearer SUA_CHAVE"
```

| Parâmetro | Regra |
| --- | --- |
| limit | De 1 a 100. Padrão: 20 campanhas por página, da mais recente para a mais antiga. |
| before\_id | Na próxima página, use data.next\_before\_id da resposta anterior. Omita na primeira consulta. |
| data.items | Campanhas, com id, nome, número, template, idioma, agendamento e progresso do disparo. |
| data.has\_more | true quando há outra página. next\_before\_id fica null quando a lista termina. |

O `id` é o mesmo usado na URL de detalhes do painel. `status: done` significa que o processamento do disparo acabou. Ainda podem chegar confirmações de entrega, leitura e falha.

O estado `paused` suspende novas tentativas da campanha. Uma requisição já em andamento pode terminar, e os webhooks de envios anteriores continuam atualizando os resultados. Pausar não cancela uma mensagem que a Meta já aceitou.

`cancelled` encerra a fila por ação do usuário e não permite retomada dessa campanha. Os destinatários ainda sem tentativa passam a `not_sent` nos resultados; uma tentativa em andamento sem confirmação permanece `uncertain`. Mensagens já aceitas continuam recebendo atualizações de entrega e leitura.

## Resultados e destinatários

### GET /public/v1/campaigns/{campaign_id}/results

cURL · consultar falhas

```bash
curl "https://api.patrociniotech.com/public/v1/campaigns/302/results?status=failed&limit=50" \
  -H "Authorization: Bearer SUA_CHAVE"
```

| Parâmetro | Regra |
| --- | --- |
| campaign\_id | Identificador positivo da campanha. Campanha inexistente ou de outra empresa retorna 404/not\_found. |
| limit | De 1 a 200 destinatários por página. Padrão: 50. |
| status | all, pending, sending, sent, delivered, read, failed, skipped, uncertain, not\_sent ou opted\_out. Padrão: all. |
| after | Copie data.next\_after da resposta anterior e mantenha o mesmo filtro. Omita na primeira página; não altere ou incremente o cursor. |

JSON · exemplo ilustrativo

```json
{
  "success": true,
  "data": {
    "campaign": {
      "id": 302,
      "name": "Oferta de novembro",
      "phone_number_id": "123456789012345",
      "template": "oferta_novembro",
      "language": "pt_BR",
      "delivery_api": "cloud",
      "status": "done",
      "total": 3,
      "accepted": 3,
      "dispatch_failed": 0,
      "created_at": "2026-11-06T12:00:00Z",
      "scheduled_at": null,
      "started_at": "2026-11-06T12:00:00Z",
      "finished_at": "2026-11-06T12:00:03Z"
    },
    "counts": {
      "pending": 0,
      "sending": 0,
      "sent": 0,
      "delivered": 1,
      "read": 1,
      "failed": 1,
      "skipped": 0,
      "uncertain": 0,
      "not_sent": 0,
      "opted_out": 1
    },
    "delivered_including_read": 2,
    "records": 3,
    "untracked": 0,
    "complete_tracking": true,
    "total_filtered": 1,
    "items": [
      {
        "to": "5511900000000",
        "name": null,
        "contact_wa_id": "5511900000000",
        "message_id": "wamid.exemplo",
        "dispatch_status": "sent",
        "status": "failed",
        "delivery_api": "cloud",
        "delivery_api_confirmed": null,
        "error_code": "marketing_recipient_limited",
        "reason": "Marketing limitado pela Meta para este destinatário",
        "attempted_at": "2026-11-06T12:00:01Z",
        "status_at": null,
        "pricing_category": null,
        "billable": null,
        "opted_out_at": null
      }
    ],
    "has_more": false,
    "next_after": null,
    "snapshot_at": "2026-11-06T12:05:00Z"
  }
}
```

## Como ler os totais

| Campo | Interpretação |
| --- | --- |
| campaign.total | Destinatários selecionados para o disparo. Não significa que receberam a mensagem. |
| campaign.delivery\_api | API selecionada para esta campanha: cloud ou marketing. A segunda opção exige template MARKETING e ativação Meta; não há fallback automático entre as rotas. |
| campaign.accepted | Envios aceitos pela API da Meta. Uma mensagem aceita ainda pode falhar depois. |
| campaign.dispatch\_failed | Contador histórico de ocorrências durante o disparo. Pode incluir exclusões e tentativas sem confirmação; não é o total de falhas definitivas. Use counts e o status de cada destinatário para decidir o tratamento. |
| campaign.paused\_at / pause\_reason | Horário UTC e motivo da pausa local. manual\_pause: ação no painel; worker\_interrupted: processamento interrompido; template\_paused, template\_not\_found ou template\_not\_approved: disponibilidade do modelo; template\_params\_mismatch, template\_param\_format ou invalid\_template: parâmetros ou formato recusados; template\_catalog\_unavailable ou template\_category\_unavailable: não foi possível conferir o catálogo ou a categoria, e a fila foi preservada; meta\_template\_paused/disabled/rejected: evento da Meta. null quando não informado ou não reconhecido. |
| counts.delivered / counts.read | Estados separados: delivered não inclui read. Para o total de entregas, use delivered\_including\_read. |
| counts.opted\_out | Pessoas que pediram para parar promoções e cuja saída foi vinculada à campanha. Sobrepõe a entrega; não some esse valor aos demais estados. |
| counts.sent | Aceitas, ainda sem entrega, leitura ou falha posterior registrada. Não considere entregues nem falhadas. |
| counts.uncertain | Tentativas sem confirmação de aceite nem de recusa. Não entram em counts.failed e não devem ser reenviadas automaticamente. |
| counts.not\_sent | Destinatários para os quais não há tentativa registrada após o encerramento ou a interrupção do disparo. Revise o motivo e a elegibilidade antes de preparar outra campanha. |
| records / untracked | records conta destinatários rastreados, inclusive excluídos. Pode superar campaign.total quando a trilha mantém exclusões da importação ou da revisão do público agendado. untracked é a diferença positiva para o público selecionado. Ausência de registro não confirma falha. |
| total\_filtered | Total que corresponde ao filtro em toda a campanha. Não é o tamanho da página nem o número restante depois do cursor. |

> Os totais são da campanha inteira e não mudam conforme a página ou o filtro. Em históricos com rastreamento incompleto, `complete_tracking` é false. Nesse caso, não trate os registros ausentes como entregas, falhas ou custo zero.

## O resultado de cada pessoa

| Campo | Interpretação |
| --- | --- |
| to / contact\_wa\_id | to é o telefone solicitado no disparo. contact\_wa\_id é o identificador confirmado pela Meta quando disponível; ele pode vir normalizado. |
| message\_id | WAMID aceito pela Meta. Pode ser usado na consulta de status da mensagem. null quando não há aceite registrado; isso não comprova que a Meta recusou o envio. |
| dispatch\_status / status | dispatch\_status registra a tentativa local; status considera a confirmação posterior de entrega. Um disparo sent pode terminar com status failed. |
| delivery\_api | API selecionada para a mensagem: cloud ou marketing; null em registros sem essa informação. A escolha da campanha não preenche retroativamente a evidência de cada mensagem. |
| delivery\_api\_confirmed | Rota comprovada pela classificação do webhook Meta: marketing\_lite confirma marketing; marketing confirma cloud. null não comprova falha nem permite inferir a rota utilizada. |
| error\_code / reason | Código estável e explicação da falha conhecida. Programe contra error\_code; reason é texto para leitura. null indica informação não registrada. |
| attempted\_at / status\_at | Horário da tentativa e da última atualização disponível na trilha. status\_at não garante o instante exato de entrega. |
| pricing\_category / billable | Categoria e indicação de cobrança recebidas da Meta. null significa não informado. Esta rota não calcula o valor da fatura. |
| opted\_out\_at | Horário da saída de promoções atribuída à campanha. A pessoa ainda pode aparecer com status read ou delivered. |

`marketing_recipient_limited` indica limitação de marketing para aquele destinatário. `marketing_experiment` indica um teste de entrega da Meta. Esses motivos não confirmam banimento do remetente e não justificam reenviar automaticamente.

## API de entrega da campanha

Na criação da campanha pelo painel, a escolha vale para o disparo: `cloud` é o padrão e `marketing` usa a Marketing Messages API da Meta somente com template `MARKETING`. A consulta pública informa a escolha em `campaign.delivery_api`. A API pública de campanhas continua sendo de leitura; para enviar uma mensagem pela integração, use [POST /messages com delivery\_api](https://patrociniotech.com/documentacao-api/mensagens.md).

Os cuidados de consentimento, bloqueios, qualidade e disponibilidade do modelo são os mesmos. A rota de marketing usa política `STRICT`; uma recusa não faz a campanha mudar silenciosamente para Cloud API. Alterar a API de entrega não é uma forma de contornar quem pediu para sair ou uma limitação da Meta.

Separe a seleção `campaign.delivery_api` da evidência `items[].delivery_api_confirmed`. A confirmação depende da classificação recebida no webhook, pode chegar depois e pode permanecer nula no histórico. O estado de entrega continua sendo informado em `status`.

## Comparar resultados das duas opções

Separe públicos equivalentes e sem sobreposição; não envie a mesma promoção duas vezes para a mesma pessoa só para comparar rotas. Use o mesmo conteúdo, critérios de seleção, período e tempo de observação após o envio. Registre a opção escolhida e mantenha aceites, entregas, falhas, incertezas e saídas separados.

| Medida | Como comparar |
| --- | --- |
| Entrega | Use delivered\_including\_read. No mundo real, mensagens lidas também foram entregues; counts.delivered e counts.read são separados apenas na resposta da API. |
| Leitura | Compare counts.read com o mesmo denominador em ambos os grupos. Não some leituras novamente ao total que já inclui read. |
| Tempo | Use o mesmo intervalo desde a tentativa. Resultados recém-enviados não são comparáveis a uma campanha que acumulou entregas durante horas. |
| Custo | Compare cobrança efetivamente informada pela Meta, na mesma moeda e categoria. Estimativa ou valor ausente não comprova economia. |

> A escolha da API não garante aumento de entrega, leitura ou conversão. Sem grupos comparáveis e tempo suficiente, a diferença observada não demonstra que a rota foi a causa.

## Ritmo e previsão de término

O painel mostra o ritmo observado das tentativas e uma estimativa para terminar de processar a fila. O tempo depende da resposta da Meta, das pausas e da gravação do resultado; não há uma quantidade fixa garantida por segundo. Entrega e leitura acontecem depois e podem continuar mudando mesmo com o disparo encerrado.

> O teto de 600 requisições por minuto da API pública não é a velocidade da campanha nem uma garantia de entrega. Ele controla chamadas autenticadas feitas pela integração. Os limites e as restrições da Meta continuam independentes.

## Pausa e retomada no painel

Administradores e supervisores com acesso à gestão de campanhas podem pausar e retomar o processamento pelo painel. Um webhook de template `PAUSED`, `DISABLED` ou `REJECTED` pausa as campanhas em processamento ou agendadas que usam o mesmo modelo, idioma e conta da Meta. Qualidade `RED` gera aviso; não equivale, por si só, a template pausado.

A aprovação posterior do template não retoma campanhas automaticamente. A retomada exige ação no painel, template aprovado e elegibilidade atual dos contatos. Ela continua apenas destinatários ainda sem tentativa registrada; pessoas com aceite, falha de tentativa ou resultado incerto ficam fora dessa retomada. Não há prazo fixo de liberação: confira o estado atual informado pela Meta.

Se a consulta do catálogo ou da categoria estiver indisponível, a campanha pausa e preserva os destinatários sem tentativa. Essa pausa não comprova rejeição do template nem falha de entrega. Tente retomar pelo painel quando a consulta voltar a funcionar.

Os motivos `marketing_api_not_ready` e `cloud_marketing_disabled` pedem revisão da configuração da API escolhida; `delivery_api_template_mismatch` indica incompatibilidade com a categoria. A fila pausa, preserva quem ainda não teve tentativa e não muda de API automaticamente. A retomada mantém a escolha original. Veja [os códigos e como agir](https://patrociniotech.com/documentacao-api/erros.md).

> A API pública oferece consulta. Pausar e retomar são ações autenticadas do painel. Não crie outra campanha para substituir uma fila pausada sem antes revisar quem já recebeu uma tentativa.

Cancelar pelo painel é definitivo para a fila dessa campanha. A confirmação não apaga o histórico nem recolhe mensagens no WhatsApp. A pausa aplicada pela Meta nunca cancela automaticamente a campanha.

## Exportar e preparar uma nova tentativa

Exporte os resultados para investigar o motivo por destinatário. A exportação registra uma fotografia; não autoriza reenviar a lista inteira. Consulte novamente os resultados e o consentimento antes de confirmar uma nova campanha.

| Situação | Tratamento |
| --- | --- |
| pending / sending | Aguarde a tentativa atual. Não abra uma campanha concorrente para essas pessoas. |
| sent / delivered / read | Não reenviar: há aceite ou entrega registrada. sent ainda aguarda confirmação posterior. |
| uncertain / send\_uncertain | Separar para conciliação. Uma resposta inválida, conexão interrompida ou falta de WAMID não comprova recusa. Não criar outro envio para contornar a incerteza. |
| not\_sent | Conferir o encerramento da fila e a elegibilidade atual. Pode compor uma nova campanha após revisão. |
| failed | Ler error\_code e corrigir a causa antes de decidir. Limitação de marketing, experimento da Meta e telefone inacessível não são convites para repetir automaticamente. |
| opted\_out / skipped | Respeitar a saída ou o motivo da exclusão. Não incluir contatos que recusaram promoções nem remover bloqueios para repetir o disparo. |

Reentregar um webhook repete a notificação para o servidor da integração; não envia uma nova mensagem no WhatsApp. Não transforme uma falha de entrega do webhook em uma nova campanha.

O evento `message.status` relata um status recebido da Meta e inclui `campaign_id` quando há vínculo com a campanha. Uma tentativa local sem WAMID não gera uma confirmação de falha da Meta. A ausência desse evento também não comprova que nada foi enviado; consulte os resultados e mantenha os casos incertos separados.

## Paginação e atualização

Continue enquanto `has_more` for true, usando `next_after` como `after`. A ordem é lexical por telefone e cada resposta lê os registros disponíveis naquele momento. Novos webhooks podem mudar o status entre páginas; para exportar ou reconciliar, guarde pelo par campanha e destinatário, atualize o mesmo registro e faça uma nova leitura depois.

A integração não deve chamar esta rota antes de cada envio. Faça consultas periódicas com pausa e respeite a cota compartilhada por chave. Filtros inválidos retornam 422; autenticação inválida retorna 401; excesso de requisições retorna 429. Um 503 é indisponibilidade temporária da consulta, não evidência de que o disparo falhou: aguarde e repita somente o GET.

---

Fonte: https://patrociniotech.com/documentacao-api/campanhas
Índice para IA: https://patrociniotech.com/documentacao-api/llms.txt
