1. Documentação
  2. Guias
  3. Campanhas
Ir para Dashboard
  • Documentação do Pushwi
  • Início rápido
  • Instalação do SDK
  • Referência do SDK
  • Soft-ask
  • Migração de outro provedor
  • Identificação de usuários
  • Segmentos
  • Campanhas
  • Descadastro e LGPD
  • Webhooks

Campanhas

Rascunho, envio, agendamento, teste A/B, métricas, edição e cancelamento de campanhas pela API.

Loading documentation…

Segmentos< PreviousDescadastro e LGPDNext >

Powered by heyo

On this page

Rascunho, envio ou agendamentoEvitando campanha duplicadaPúblicoConteúdoEnvio no fuso do assinantePrioridadeRecorrênciaTeste A/BAcompanhando o envioMétricasEditandoCancelando e excluindo

Depois de criada, a campanha aparece no painel. Pela API, dá para consultá-la com as métricas, editar enquanto ela não começou a sair, cancelar um agendamento e excluir.

Rascunho, envio ou agendamento

O campo action decide o que acontece:

actionResultadoStatus inicial
draft (padrão)Salva para alguém revisar e enviar pelo paineldraft
sendEntra na fila de envio na horaqueued
scheduleSai em scheduled_atqueued
bash
curl https://api.pushwi.com/v1/campaigns \  -H "Authorization: Bearer $PUSHWI_KEY" \  -H "Content-Type: application/json" \  -d '{    "action": "schedule",    "scheduled_at": "2026-10-10T09:00:00-03:00",    "content": {      "title": "Começou a semana do cliente",      "body": "Descontos de até 40% até domingo.",      "url": "https://loja.exemplo.com.br/semana-do-cliente"    }  }'

Sem fuso, scheduled_at é lido no fuso do site, configurado no painel (padrão America/Sao_Paulo): 2026-10-10T09:00:00 sai às 9h de Brasília. Com fuso (-03:00, Z), vale o que veio na data. Se o seu sistema guarda horários em UTC, mande com Z para não haver dúvida. O agendador confere as campanhas vencidas a cada minuto, então o envio começa até um minuto depois do horário marcado.

Uma data no passado não gera erro. A campanha sai na próxima verificação.

Evitando campanha duplicada

Se a chamada cair por timeout, você não sabe se a campanha foi criada. Mande o cabeçalho Idempotency-Key com um valor único por campanha (o ID do pedido no seu sistema, um UUID) e repita a chamada com a mesma chave e o mesmo corpo sem medo:

bash
curl https://api.pushwi.com/v1/campaigns \  -H "Authorization: Bearer $PUSHWI_KEY" \  -H "Idempotency-Key: pedido-1234-entrega" \  -H "Content-Type: application/json" \  -d '{ "action": "send", "content": { "title": "Seu pedido saiu", "body": "Chega hoje." } }'
SituaçãoResposta
Primeira chamada com a chave201, a campanha é criada
Mesma chave e mesmo corpo, em até 24 horas201 com a resposta original e o cabeçalho Idempotent-Replayed: true. Nada é criado nem enviado de novo.
Mesma chave com outro corpo422
Chave vazia ou com mais de 255 caracteres422

A chave vale por site e expira em 24 horas. Uma chamada recusada na validação (422 dos campos) não consome a chave. Sem o cabeçalho, cada chamada cria uma campanha.

Público

Sem segment_id, a campanha vai para todos os dispositivos ativos do site. Com ele, só para os que atendem ao segmento no momento do envio.

Quando a campanha começa a sair, o nome do segmento fica guardado nela, no campo segment_name. Se o segmento for renomeado ou apagado depois, a campanha continua mostrando para quem foi enviada. Um segmento só pode ser apagado quando nenhuma campanha pendente e nenhum feed RSS o usa.

Conteúdo

json
{  "content": {    "title": "Seu pedido saiu para entrega",    "body": "Chega hoje até as 18h.",    "url": "https://loja.exemplo.com.br/pedidos/1234",    "icon_url": "https://loja.exemplo.com.br/icone-192.png",    "image_url": "https://loja.exemplo.com.br/banners/entrega.jpg",    "buttons": [      { "title": "Acompanhar", "action": "acompanhar" },      { "title": "Falar com a loja", "action": "contato" }    ]  }}

O título também é o nome da campanha no painel. Até dois botões, e os dois abrem a mesma url: o action só identifica qual foi clicado. A imagem grande aparece no Chrome e no Edge para desktop e Android; Safari e Firefox ignoram.

Envio no fuso do assinante

Com send_in_user_tz: true, o Pushwi pega o horário de scheduled_at no fuso do site e entrega nesse mesmo horário de relógio no fuso de cada assinante. Agendou para 9h? Quem está em Lisboa recebe às 9h de Lisboa, e quem está em Manaus, às 9h de Manaus.

O fuso de cada assinante é estimado pelo país. Quem já passou do horário no momento do envio recebe na hora. Agende no fuso mais adiantado do seu público para que todos recebam no horário certo.

Prioridade

breaking: true coloca a campanha na frente da fila de envio, à frente de campanhas comuns que estejam saindo ao mesmo tempo. Use para notícia urgente, não como padrão.

Recorrência

recurrence: "daily" ou "weekly" cria uma cópia da campanha agendada para um dia ou uma semana depois de cada envio. A cópia segue o mesmo caminho: quando sai, agenda a próxima. Para parar, cancele a próxima campanha agendada, pelo painel ou pela API. Ela aparece em GET /v1/campaigns?status=queued.

Teste A/B

json
{  "action": "send",  "ab_test": true,  "test_fraction": 0.2,  "content": { "title": "Promoção relâmpago", "body": "Só hoje.", "url": "https://loja.exemplo.com.br" },  "variants": [    { "name": "Urgência", "title": "Últimas horas!", "body": "A promoção acaba à meia-noite." },    { "name": "Desconto", "title": "40% de desconto", "body": "Em toda a loja, só hoje." }  ]}

Com test_fraction entre 0 e 1, o teste tem duas fases. Primeiro, essa fração do público (20% no exemplo) recebe as variantes, divididas pelo weight de cada uma. Duas horas depois, a variante com a maior taxa de clique vai para o restante.

Com test_fraction ausente, 0 ou 1, não há segunda fase: o público inteiro é dividido entre as variantes.

As variantes trocam título, texto e URL; variante sem url usa a de content. Ícone, imagem e botões vêm sempre de content. O webhook campaign.sent traz winner_variant_id quando o teste termina.

Acompanhando o envio

A campanha passa por estes status:

StatusSignificado
draftRascunho
queuedEsperando o horário ou a vez na fila
queuingMontando a lista de destinatários
sendingEntregando
sentTerminou
failedNão saiu
canceledCancelada antes de começar a sair

Para saber o resultado sem consultar, use os webhooks campaign.sent e campaign.failed. Para ler a campanha a qualquer momento, use Obter campanha ou Listar campanhas, que aceita o filtro status e é paginada.

Métricas

A partir de queuing, a campanha vem com o campo stats. Em draft, queued e canceled, ele é null.

json
{  "id": 1287,  "status": "sent",  "stats": {    "recipients": 18430,    "sent": 18102,    "delivered": 16877,    "clicked": 905,    "click_rate": 5  }}
CampoSignificado
recipientsDispositivos no público no momento do envio
sentEnvios aceitos pelo serviço de push do navegador (Google, Apple, Mozilla, Microsoft)
deliveredNotificações que o service worker confirmou ter exibido. Fica abaixo de sent porque nem todo navegador avisa.
clickedCliques na notificação ou num dos botões
click_rateclicked / sent, em %, com uma casa decimal

Em teste A/B, cada item de variants traz o próprio stats com sent, clicked e click_rate. Os números podem levar até um minuto para aparecer, porque os eventos chegam em lote.

Para os totais do site por dia, de todas as campanhas juntas, use o relatório diário.

Editando

PATCH /v1/campaigns/{id} altera uma campanha em draft ou queued. Só muda o que vier no corpo:

bash
curl -X PATCH https://api.pushwi.com/v1/campaigns/1287 \  -H "Authorization: Bearer $PUSHWI_KEY" \  -H "Content-Type: application/json" \  -d '{ "content": { "body": "Agora com frete grátis também." } }'
  • Campos de content são mesclados um a um. content.buttons e variants, quando vêm, substituem a lista inteira.
  • action muda o destino: draft volta para rascunho, send envia agora e schedule agenda para scheduled_at.
  • Para mudar só o horário de uma campanha já agendada, mande scheduled_at sozinho. Numa campanha que não está agendada, é preciso mandar action: "schedule" junto.

A resposta é a campanha completa. Se o envio já começou (queuing, sending) ou terminou, a resposta é 409.

Cancelando e excluindo

RotaVale paraEfeito
POST /v1/campaigns/{id}/cancelqueuedA campanha passa para canceled e não sai mais. Ela continua visível, no painel e na API.
DELETE /v1/campaigns/{id}draft, queued, canceledApaga a campanha. Responde 204.

Fora desses status, as duas rotas respondem 409. Uma campanha cancelada não volta para a fila. Para enviar o mesmo conteúdo, crie outra campanha ou duplique pelo painel.

O cancelamento é seguro mesmo no limite: se o envio começar no mesmo instante, só um dos dois acontece. Ou a campanha fica canceled e não sai, ou ela sai e o cancelamento recebe 409.