Campanhas
Rascunho, envio, agendamento, teste A/B, métricas, edição e cancelamento de campanhas pela API.
Loading documentation…
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.
O campo action decide o que acontece:
action | Resultado | Status inicial |
|---|---|---|
draft (padrão) | Salva para alguém revisar e enviar pelo painel | draft |
send | Entra na fila de envio na hora | queued |
schedule | Sai em scheduled_at | queued |
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.
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:
| Situação | Resposta |
|---|---|
| Primeira chamada com a chave | 201, a campanha é criada |
| Mesma chave e mesmo corpo, em até 24 horas | 201 com a resposta original e o cabeçalho Idempotent-Replayed: true. Nada é criado nem enviado de novo. |
| Mesma chave com outro corpo | 422 |
| Chave vazia ou com mais de 255 caracteres | 422 |
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.
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.
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.
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.
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.
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.
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.
A campanha passa por estes status:
| Status | Significado |
|---|---|
draft | Rascunho |
queued | Esperando o horário ou a vez na fila |
queuing | Montando a lista de destinatários |
sending | Entregando |
sent | Terminou |
failed | Não saiu |
canceled | Cancelada 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.
A partir de queuing, a campanha vem com o campo stats. Em draft, queued e canceled, ele é null.
| Campo | Significado |
|---|---|
recipients | Dispositivos no público no momento do envio |
sent | Envios aceitos pelo serviço de push do navegador (Google, Apple, Mozilla, Microsoft) |
delivered | Notificações que o service worker confirmou ter exibido. Fica abaixo de sent porque nem todo navegador avisa. |
clicked | Cliques na notificação ou num dos botões |
click_rate | clicked / 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.
PATCH /v1/campaigns/{id} altera uma campanha em draft ou queued. Só muda o que vier no corpo:
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.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.
| Rota | Vale para | Efeito |
|---|---|---|
POST /v1/campaigns/{id}/cancel | queued | A campanha passa para canceled e não sai mais. Ela continua visível, no painel e na API. |
DELETE /v1/campaigns/{id} | draft, queued, canceled | Apaga 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.