Saltar para a documentação
API

Enviar para audiências

Envia uma mensagem para todos em uma ou mais audiências, como cópia separada para cada pessoa e personalizada a partir de cada contacto. Cada cópia tem exatamente um destinatário e nem cc nem bcc, por isso ninguém vê para quem mais foi, e cada cópia é um e-mail normal com o seu próprio id `msg_`, eventos, seguimento e webhooks. A chamada responde `202` de imediato e o envio continua em segundo plano, por isso acompanhe-o com `GET /broadcasts/{id}`.

POSTapi.openemail.uk/broadcasts

Executa a chamada real contra o seu espaço de trabalho, com a sua própria chave.

POST /broadcasts

Envia uma mensagem para todos em uma ou mais audiências, como cópia separada para cada pessoa e personalizada a partir de cada contacto. Cada cópia tem exatamente um destinatário e nem cc nem bcc, por isso ninguém vê para quem mais foi, e cada cópia é um e-mail normal com o seu próprio id msg_, eventos, seguimento e webhooks. A chamada responde 202 de imediato e o envio continua em segundo plano, por isso acompanhe-o com GET /broadcasts/{id}.

Exemplo

Precisa de emails:send e audiences:read. audienceIds tem de 1 a 10 ids. O corpo vem de html e/ou text, ou de um template guardado, nunca de ambos, e subject é obrigatório a não ser que o modelo o forneça.

curl
curl -X POST "$OE/broadcasts" -H "$AUTH" -H 'content-type: application/json' -d '{  "audienceIds": ["aud_4c1b8e2a7d9f05c36b4e8a71"],  "from": "Acme <[email protected]>",  "subject": "{{firstName|Hello}}, the September release is out",  "html": "<p>Hi {{firstName|there}},</p><p>Here is what changed this month.</p>",  "text": "Hi {{firstName|there}}, here is what changed this month. Unsubscribe: {{unsubscribeUrl}}",  "tags": { "campaign": "release-2026-09" },  "scheduledAt": "PT2H"}'
Resposta
{  "object": "broadcast",  "id": "brd_5a8c1e3f7b2d94a06c8e1f3b",  "status": "scheduled",  "mode": "live",  "source": "api",  "audienceIds": ["aud_4c1b8e2a7d9f05c36b4e8a71"],  "from": "Acme <[email protected]>",  "subject": "{{firstName|Hello}}, the September release is out",  "counts": {    "recipients": 412,    "created": 0,    "skipped": 0,    "failedToQueue": 0,    "queued": 0,    "sending": 0,    "sent": 0,    "failed": 0,    "cancelled": 0  },  "lastError": null,  "scheduledAt": "2026-09-23T14:00:00.000Z",  "startedAt": null,  "completedAt": null,  "cancelledAt": null,  "createdAt": "2026-09-23T12:00:00.000Z",  "updatedAt": "2026-09-23T12:00:00.000Z",  "replayed": false}

A resposta é queued, ou scheduled com scheduledAt, que aceita um instante ISO 8601 ou uma duração como PT2H, no máximo a 365 dias. counts.recipients é a estimativa tirada agora, e os outros contadores começam em 0. O cabeçalho Location indica a difusão.

Pode repetir com segurança com um cabeçalho Idempotency-Key: a mesma chave responde 200 com a difusão que a primeira chamada criou e Idempotency-Replayed: true, e a mesma chave com outro corpo dá 422 idempotency_key_reuse. Sem chave, enviar o mesmo corpo duas vezes envia a difusão duas vezes.

As cópias não são arquivadas na pasta Enviados, porque a difusão é o registo. GET /emails?broadcastId=brd_5a8c1e3f7b2d94a06c8e1f3b lista-as, uma por pessoa.

Quem a recebe

Todos os contactos de pelo menos uma das audiências, contados uma vez por mais audiências que os contenham. Ficam de fora dois tipos de contacto: o que cancelou a subscrição de todas as audiências escolhidas em que está, e o que tem o endereço na lista de supressão após uma devolução ou uma queixa, ou porque alguém o adicionou. Um contacto adicionado a uma das audiências depois da chamada, mas antes de o envio lá chegar, é incluído.

O envio percorre as audiências 50 pessoas de cada vez e entrega cada cópia ao mesmo circuito que POST /emails usa, por isso cada cópia é repetida, seguida e reportada como qualquer outra mensagem. POST /broadcasts/preview devolve o número de que esta chamada partiria, sem enviar nada.

O envio inteiro é comparado com os envios mensais do plano antes de se escrever qualquer coisa. Uma difusão que a quota não consegue cobrir é recusada com 429 send_quota_exceeded e não deixa nada para trás. Cada cópia conta como um envio.

Campos de fusão

subject, html e text são preenchidos para cada pessoa. Cada campo aceita um valor alternativo depois de uma barra, usado quando o contacto não tem valor para ele, por isso {{firstName|there}} passa a "there" para um contacto guardado sem nome. Os valores são escapados em html, são permitidos espaços dentro das chavetas e qualquer outro {{…}} fica exatamente como foi escrito.

CampoPreenchido com
`{{firstName}}`A primeira palavra do nome do contacto.
`{{lastName}}`O resto do nome do contacto depois da primeira palavra.
`{{name}}`O nome completo do contacto.
`{{email}}`O endereço para onde vai a cópia.
`{{unsubscribeUrl}}`A ligação que cancela a subscrição desta pessoa nestas audiências.

Com template em vez de um corpo, os mesmos cinco valores são passados como props, mas só as props que o modelo declara. Um modelo que declara firstName recebe-o, e uma prop que não declara nunca é enviada, por isso as cópias nunca falham por uma prop desconhecida. Tudo o que puser em template.props vai igual para todas as cópias.

Cancelar subscrição

Cada cópia leva List-Unsubscribe e List-Unsubscribe-Post: List-Unsubscribe=One-Click. É isso que permite a um cliente de correio mostrar o seu próprio botão de cancelar subscrição, e o que os grandes fornecedores de caixas de correio exigem ao correio em massa.

Um corpo html ou text que não coloque {{unsubscribeUrl}} por si recebe um rodapé de uma linha: "You are receiving this because you are on this mailing list. Unsubscribe". Um modelo é enviado exatamente como está, por isso ponha {{unsubscribeUrl}} no modelo.

A ligação abre uma página com um botão para cancelar a subscrição, por isso um analisador de ligações que a obtenha não cancela a subscrição de ninguém, enquanto o pedido de um clique feito por um cliente de correio cancela-a de imediato. Em ambos os casos, a pessoa fica marcada sem subscrição em todas as audiências para onde esta difusão foi, o que aparece como unsubscribedAt em GET /audiences/{id}/contacts. As outras audiências, o contacto e o correio que lhe é enviado uma mensagem de cada vez não são afetados.

Recusas

EstadoCódigoQuando
403from_address_forbiddenA chave não pode enviar como from.
404audience_not_foundUm id em audienceIds não indica nenhuma audiência neste workspace.
409domain_not_sendableO domínio de from ainda não consegue assinar correio, tal como em POST /emails.
422no_recipientsAs audiências estão vazias, ou todos nelas cancelaram a subscrição ou estão suprimidos.
422invalid_parameterSem corpo, html ou text ao lado de template, sem subject e sem modelo, mais de 10 audiências ou 8 etiquetas, ou um scheduledAt que não está no futuro ou está a mais de 365 dias.
422template_not_foundO modelo não se resolve. As outras recusas de modelo também indicam template.*.
422capability_unsupportedA chave está limitada a endereços concretos. As audiências pertencem a todo o workspace.
429send_quota_exceededO plano não consegue cobrir uma cópia para todos este mês.

Sem anexos, cc, bcc, tradução nem encriptação. tags aceita até 8, e cada cópia leva também broadcast_id, que o servidor acrescenta.