# 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.

Fonte: https://couryo.com/docs/campaigns

Uma **campanha** manda um e-mail para um público de [contatos](https://couryo.com/docs/contacts.md): 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](https://couryo.com/docs/suppressions.md) 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](https://couryo.com/docs/limits.md) 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. `neq` també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 `tags` no [cadastro do contato](https://couryo.com/docs/contacts.md).
- `POST /v1/contacts/count` com `{ "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

```bash title="Criar a campanha (rascunho)"
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](https://couryo.com/docs/templates.md) (`template_id`) ou assunto com `html` e/ou `text` próprios, feitos no [editor](https://couryo.com/docs/template-editor.md). 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 de `variables` e `{{unsubscribe_url}}`. Use um [valor padrão](https://couryo.com/docs/templates.md#valor-padrao-variavelpadrao) 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-Unsubscribe` em 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_emailed` e `never_emailed_share`: quem nunca recebeu e-mail deste projeto. Acima de 30%, o aviso `never_emailed` lembra que lista fria derruba a entrega;
- `needs_review`: se vai para revisão (abaixo);
- `review`: a [revisão com IA](https://couryo.com/docs/ai.md) do conteúdo, grátis;
- `warnings` e `can_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](https://couryo.com/docs/limits.md). Se o limite diário acabar, a campanha espera e continua sozinha; `status_message` explica.
- 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 traz `paused_reason`: `manual`, `bounce_rate`, `limit`, `domain`, `plan` ou `content`.

## 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](https://couryo.com/docs/limits.md) continuam valendo por cima: descida gradual, pausa do marketing e revisão.

## Métricas

`GET /v1/campaigns/{id}/stats`:

```json title="Resposta"
{
  "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](https://couryo.com/docs/tracking.md)). `opened_machine` conta as abertas só pela proteção de privacidade do programa de e-mail.
- `clicks` em `top_links` são pessoas (e-mails únicos); `total` são todos os cliques.
- Cada e-mail da campanha leva a tag `campaign` com o id, então aparece em `GET /v1/emails?tag=campaign:cmp_...` e nos [webhooks](https://couryo.com/docs/webhooks.md).

## 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](https://couryo.com/docs/mcp.md), 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).
