Receba novidades do Hedhog no seu e-mail
Novos lançamentos, receitas e breaking changes — sem spam.
Submódulo Campaign
recipient-lists
Listas nomeadas de destinatários que as campanhas alvejam. Suporta entrada manual, importação por CSV, sincronização com o CRM e cadastro público.
Caminho de origem: libraries/campaign/src/services/campaign-recipient-list.service.ts, campaign-realtime.service.ts, dto/public-signup.dto.ts
Arquivo do módulo: campaign.module.ts
Introdução
O submódulo Recipient Lists modela `campaign_recipient_list`, o contêiner de público que uma campanha aponta via `recipient_list_id`. Cada lista carrega um slug único e validado (letras minúsculas, números, hifens, no mínimo 2 caracteres — gerado automaticamente a partir do nome se não fornecido), uma classificação de `source` ("manual" | "import" | "crm" | "mixed") que reflete como seus destinatários foram populados e contadores consolidados (`total_recipients`, `total_active`, `total_unsubscribed`, `total_suppressed`, `total_invalid`) que o CampaignRecipientListService recalcula após cada mutação, em vez de computar na leitura. Todas as rotas são montadas em duplicidade tanto sob `/campaign/lists/*` quanto `/campaign/recipient-lists/*` — o controller registra cada handler duas vezes com o suporte a múltiplos decorators do NestJS — de modo que ambas as convenções de nomenclatura resolvem de forma idêntica; esta documentação usa `/campaign/recipient-lists/*` como a forma canônica.
Destinatários podem ser adicionados a uma lista de três maneiras. JSON inline (`POST .../recipients` com um array de objetos `{ email, name?, ... }` ou um atalho `{ email }` único) faz upsert por e-mail dentro da lista. A sincronização com o CRM (`person_ids` no mesmo endpoint) resolve o contato primário do tipo EMAIL de cada Person do CRM, pulando pessoas sem e-mail válido e reportando-as de volta em um array `skipped`, e então muda o `source` da lista para "mixed" (ou "crm" se todos os destinatários vieram do CRM) assim que pelo menos uma pessoa é adicionada. A importação por CSV é um fluxo em duas etapas: `POST .../recipients/import/preview` faz o parsing do arquivo enviado (parser de CSV artesanal e customizado, suportando tanto delimitadores de vírgula quanto de ponto e vírgula e campos entre aspas, limitado a 10 MB / reforçado novamente em 5000 linhas de dados) e retorna as colunas detectadas mais uma amostra de 20 linhas sem persistir nada; `POST .../recipients/import` recebe o mesmo arquivo mais um `mapping` JSON das colunas do CSV para os campos de destinatário e realiza o upsert-por-e-mail de fato, opcionalmente vinculando cada linha importada a uma empresa existente do CRM via `company_id`.
O cadastro público (`POST /campaign/lists/:slug/signup`, não autenticado) permite que uma lista aceite inscrições self-service. Ele só funciona quando `allow_public_signup` é true na lista; quando `enable_captcha` também é true, o Integration Profile de CAPTCHA configurado (reCAPTCHA, Cloudflare Turnstile ou Altcha) é invocado para validar o `captcha_token` enviado antes de o e-mail sofrer upsert. Este é o ponto de entrada típico para formulários de inscrição em newsletter incorporáveis.
O submódulo também hospeda o cursor de tempo real da campanha (`GET /campaign/realtime/cursor`, `GET /campaign/realtime/stream`): cada mutação de lista chama `CampaignRealtimeService.publish()`, incrementando um contador de sequência em memória que as UIs de admin consultam por polling ou assinam via Server-Sent Events para saber quando refazer o fetch dos dados da lista, sem que o servidor rastreie o estado por cliente.
Endpoints HTTP
15 endpoints
Obtém o cursor de atualização em tempo real atual (número de sequência e timestamp da última atualização) para refresh baseado em polling.
Abre um stream de Server-Sent Events que envia o cursor atualizado sempre que uma lista de destinatários muda (criação, atualização, exclusão, mutação de destinatário).
Estatísticas agregadas em todas as listas de destinatários: total de listas e contadores somados de destinatários/ativos/descadastrados/suprimidos/inválidos. Também disponível em /campaign/lists/stats.
Lista paginada de listas de destinatários. Também disponível em /campaign/lists.
- Query
- page, pageSize, search, status, source
Cria uma lista de destinatários. Também disponível em /campaign/lists.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | yes | — |
| slug | string | no | Auto-generated from name if omitted; lowercase letters/numbers/hyphens, min 2 chars, must be unique |
| description | string | no | — |
| source | "manual" | "import" | "crm" | "mixed" | no | Default: "manual" |
| status | "active" | "inactive" | no | Default: "active" |
| allow_public_signup | boolean | no | Default: false |
| enable_captcha | boolean | no | Default: false |
| captcha_integration_profile_id | number | no | Required when enable_captcha is true |
| metadata | object | no | — |
Exclusão em massa de listas de destinatários. Também disponível em /campaign/lists.
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| ids | number[] | yes | IDs to delete |
Obtém uma lista de destinatários por ID. Também disponível em /campaign/lists/:id.
- Params
- id (int)
Atualiza uma lista de destinatários. Apenas os campos fornecidos são alterados. Também disponível em /campaign/lists/:id.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| name | string | no | — |
| description | string | no | — |
| source | "manual" | "import" | "crm" | "mixed" | no | — |
| status | "active" | "inactive" | no | — |
| metadata | object | no | — |
| slug | string | no | Must remain unique |
| allow_public_signup | boolean | no | — |
| enable_captcha | boolean | no | — |
| captcha_integration_profile_id | number | no | — |
Exclui uma única lista de destinatários. Também disponível em /campaign/lists/:id.
- Params
- id (int)
Lista paginada de destinatários em uma lista específica. Também disponível em /campaign/lists/:id/recipients.
- Params
- id (int)
- Query
- page, pageSize, search, status
Pré-visualiza uma importação de CSV: faz o parsing de delimitadores/aspas e retorna as colunas detectadas mais uma amostra de 20 linhas sem persistir dados. Rejeita arquivos com mais de 5000 linhas de dados. Também disponível em /campaign/lists/:id/recipients/import/preview.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| file | file (CSV, max 10 MB) | yes | multipart/form-data upload; text/csv or application/vnd.ms-excel |
Importa destinatários de um arquivo CSV. Faz upsert por e-mail dentro da lista e opcionalmente cria registros de Person vinculados no CRM. Também disponível em /campaign/lists/:id/recipients/import.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| file | file (CSV, max 10 MB) | yes | multipart/form-data upload |
| mapping | string (JSON) | yes | JSON object mapping CSV column names to recipient fields (e.g. {"Email":"email","Nome":"name"}) |
| company_id | number | no | CRM company ID to associate imported recipients/persons |
Adiciona destinatários a uma lista a partir de IDs de person do CRM ou de dados inline. Faz upsert por e-mail e recalcula os contadores da lista. Também disponível em /campaign/lists/:id/recipients.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| person_ids | number[] | no | CRM person IDs; auto-resolves primary EMAIL contact. When provided, other fields are ignored |
| recipients | object[] | no | Array of { email, name?, first_name?, last_name?, company?, phone?, status?, source?, person_id?, metadata? } |
| string | no | Shorthand for adding a single recipient by email |
Remove destinatários específicos de uma lista. Também disponível em /campaign/lists/:id/recipients.
- Params
- id (int)
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| ids | number[] | yes | Recipient IDs to remove from this list |
Cadastro público em uma lista de destinatários identificada por slug. Só funciona quando a lista tem allow_public_signup habilitado. Valida o CAPTCHA (reCAPTCHA, Cloudflare Turnstile ou Altcha) quando enable_captcha está definido e então faz upsert do destinatário como ativo.
- Params
- slug (string) — public slug of the recipient list
Body
| Field | Type | Required | Notes |
|---|---|---|---|
| string | yes | Valid email address | |
| name | string | no | — |
| first_name | string | no | — |
| last_name | string | no | — |
| company | string | no | — |
| phone | string | no | — |
| captcha_token | string | no | Required when the list has enable_captcha set |