Guia do desenvolvedorAutomações
Campanhas
Campanhas no Couryo para mandar um e-mail a todos os contatos ou a um segmento por atributos e tags, com agendamento, teste, revisão antes de disparar, pausa e métricas de entrega, abertura e clique. Sem cobrança por contato.
Uma campanha manda um e-mail para um público de contatos: todos os inscritos do projeto ou um segmento. É o envio para lista (newsletter, lançamento, promoção, aviso), sempre no fluxo marketing, com descadastro em um clique e a lista de supressão respeitada.
Sem cobrança por contato. Os e-mails da campanha contam na cota do plano e mais nada.
Quem pode disparar#
| Plano | Campanhas |
|---|---|
| Grátis | monta e testa rascunhos; não dispara |
| Pro | com o complemento Automações (R$ 49 / US$ 9 por mês) |
| Escala e Empresa | incluídas |
Também é preciso estar no nível de confiança 1 ou mais (um domínio verificado). Sem isso, o disparo responde 403 campaigns_not_available, com upgrade_options mostrando o que libera.
Público#
- Todos os contatos inscritos (
{ "type": "all" }). - Um segmento (
{ "type": "segment", "match": "all" | "any", "conditions": [...] }): até 20 condições, todas (E) ou pelo menos uma (OU).
field |
op |
Exemplo |
|---|---|---|
attribute (com key) |
eq, neq, contains, exists |
{ "field": "attribute", "key": "plano", "op": "eq", "value": "pro" } |
tag |
eq (tem a tag), neq (não tem), contains, exists (tem alguma) |
{ "field": "tag", "op": "eq", "value": "cliente" } |
email |
eq, neq, contains, exists |
{ "field": "email", "op": "contains", "value": "@empresa.com.br" } |
- As comparações ignoram maiúsculas.
neqtambém pega quem não tem o atributo. - Quem se descadastrou, voltou, reclamou ou foi suprimido à mão fica de fora sozinho.
- As tags do contato vêm em
tagsno cadastro do contato. POST /v1/contacts/countcom{ "audience": ... }conta o público sem enviar nada:{ total, subscribed, suppressed }.- O público fica fixo quando o envio começa: quem entrar depois não recebe esta campanha.
Criar#
curl https://api.couryo.com/v1/campaigns \
-H "Authorization: Bearer $COURYO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: campanha-outubro" \
-d '{
"name": "Coleção de outubro",
"from": "Loja <novidades@loja.com.br>",
"audience": { "type": "segment", "match": "all",
"conditions": [{ "field": "tag", "op": "eq", "value": "cliente" }] },
"subject": "Oi, {{nome|cliente}}: chegou a coleção nova",
"html": "<p>Oi, {{nome|cliente}}!</p><p><a href=\"https://loja.com.br/colecao\">Ver a coleção</a></p>"
}'- Conteúdo: um template salvo (
template_id) ou assunto comhtmle/outextpróprios, feitos no editor. Com template,subject(quando vem) troca o assunto do template. - Variáveis: os atributos do contato (
{{nome}}, também{{contact.nome}}),{{email}}, os valores fixos devariablese{{unsubscribe_url}}. Use um valor padrão para quem não tem o atributo:{{nome|cliente}}. Sem valor e sem padrão, o trecho sai vazio; assunto vazio para um contato vira erro só para ele. - Descadastro: o link de descadastro entra no fim do e-mail quando o conteúdo não tem, e o
List-Unsubscribeem um clique (RFC 8058) vai sempre. PATCH /v1/campaigns/{id}muda rascunhos e agendadas. Numa campanha pausada, o conteúdo muda para quem falta, mas o público continua fixo.
Antes de disparar#
POST /v1/campaigns/{id}/preflight não envia nada e devolve:
recipients: a contagem real de destinatários agora;suppressed: quantos ficam de fora;never_emailedenever_emailed_share: quem nunca recebeu e-mail deste projeto. Acima de 30%, o avisonever_emailedlembra que lista fria derruba a entrega;needs_review: se vai para revisão (abaixo);review: a revisão com IA do conteúdo, grátis;warningsecan_send: o que impede o disparo (plano, nível, remetente, domínio, conteúdo, público vazio).
POST /v1/campaigns/{id}/test manda o conteúdo real, com [Teste] no assunto, para até 5 endereços das pessoas da sua conta ({ "to": ["voce@loja.com.br"] }). O teste não entra nas métricas.
Disparar, agendar, pausar#
| Chamada | O que faz |
|---|---|
POST /v1/campaigns/{id}/send |
começa agora |
POST /v1/campaigns/{id}/schedule com { "scheduled_at" } |
começa na hora marcada (até 90 dias) |
POST /v1/campaigns/{id}/pause |
para entre um lote e outro; vale também para agendadas |
POST /v1/campaigns/{id}/resume |
continua de onde parou (plano e nível conferidos de novo) |
POST /v1/campaigns/{id}/cancel |
quem ainda não recebeu não recebe; o que saiu continua nas métricas |
- O envio sai em lotes, no ritmo do motor e dentro dos limites do seu nível. Se o limite diário acabar, a campanha espera e continua sozinha;
status_messageexplica. - Cada contato recebe uma vez, mesmo se o servidor reiniciar no meio de um lote.
- Status:
draft,scheduled,in_review,sending,paused,sent,cancelled. Pausada trazpaused_reason:manual,bounce_rate,limit,domain,planoucontent.
Proteções#
- Primeira campanha grande: a primeira campanha da conta acima de 5 mil destinatários passa por uma revisão antes de começar (
status: in_review). O agente libera na hora os casos claros (nível 2 ou mais, lista com histórico de envio, taxas limpas); os outros recebem um olhar humano, em geral em até 1 dia útil. A resposta chega por e-mail. Depois disso, as próximas seguem direto. - Pausa automática por devolução: se mais de 5% dos primeiros mil e-mails voltarem, a campanha pausa sozinha (
paused_reason: bounce_rate) e você recebe um e-mail com os números. Os endereços que voltaram já vão para a supressão; limpe a lista antes de retomar. - As regras da conta continuam valendo por cima: descida gradual, pausa do marketing e revisão.
Métricas#
GET /v1/campaigns/{id}/stats:
{
"campaign_id": "cmp_8k2m4q9w1x7z3abc",
"recipients": 1203, "sent": 1198, "delivered": 1180, "bounced": 18, "complained": 1,
"opened": 484, "opened_machine": 170, "clicked": 79, "unsubscribed": 5, "skipped": 5, "failed": 0,
"rates": { "delivery": 0.985, "bounce": 0.015, "complaint": 0.0008, "open": 0.4102, "click": 0.0669, "click_to_open": 0.1632, "unsubscribe": 0.0042 },
"top_links": [{ "url": "https://loja.com.br/colecao", "clicks": 66, "total": 91 }],
"opens_estimated": true
}- Aberturas são estimadas (veja Rastreio de abertura e clique).
opened_machineconta as abertas só pela proteção de privacidade do programa de e-mail. clicksemtop_linkssão pessoas (e-mails únicos);totalsão todos os cliques.- Cada e-mail da campanha leva a tag
campaigncom o id, então aparece emGET /v1/emails?tag=campaign:cmp_...e nos webhooks.
Pelo painel e por agentes#
No painel, Campanhas monta tudo em passos (público, conteúdo, revisão, disparo) e mostra a página da campanha com as métricas. No MCP, as ferramentas create_campaign, list_campaigns, get_campaign_stats, send_campaign e pause_campaign; send_campaign só dispara com confirm: true (sem ele, devolve a checagem e a contagem).